package com.motu.monstercity.server.game.logic;

import com.motu.monstercity.module.common.iap.IapGift;
import com.motu.monstercity.module.common.servermanager.ServerInfo;
import com.motu.monstercity.module.common.servermanager.ServerManager;
import com.motu.monstercity.protocol.Common;
import com.motu.monstercity.protocol.Common.PBRankMember;
import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.protocol.CsGameSystem;
import com.motu.monstercity.server.game.base.AllParam;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.LockKey;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.act.*;
import com.motu.monstercity.server.game.commondata.mail.MailConstant;
import com.motu.monstercity.server.game.commondata.rank.RankReward;
import com.motu.monstercity.server.game.commondata.shop.Shop;
import com.motu.monstercity.server.game.commondata.system.SystemConstant;
import com.motu.monstercity.server.game.log.LogType;
import com.motu.monstercity.server.game.userdata.*;
import com.motu.vertx.module.utility.main.MainService;
import com.motu.vertx.module.utility.model.BaseModel;
import com.motu.vertx.module.utility.redis.RedisTools;
import com.motu.vertx.module.utility.toolset.ErrorWord;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.Future;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.shareddata.Lock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

public class RankActManager extends RankActUserData {
    private static Logger logger = LoggerFactory.getLogger(RankActManager.class);

    public static void loadActInfo(Common.PBUserData.Builder pbUserData, UserInfo userInfo) {
        int localDays = RankActManager.getActDays(ActConfig.GROUP_ID_LOCAL);
        long curTime = TimeUtils.getCurTime();
        int serverId = userInfo.getServerId();
        ServerInfo serverInfo = ServerManager.getServerInfo(serverId);
        long today = TimeUtils.getStartTimeOfDay(curTime);
        int serverOpenDays = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        Common.PBRankActTimeInfo.Builder response = Common.PBRankActTimeInfo.newBuilder();
        if (serverOpenDays <= localDays) { // 本服活动
            response.setActGroupId(ActConfig.GROUP_ID_LOCAL);
            response.setStatus(1);
            ConcurrentHashMap<Integer, ActConfig> actConfigMap = RankActManager.getActConfigList(ActConfig.GROUP_ID_LOCAL);
            ActConfig actConfig = RankActManager.getActConfig(serverOpenDays, actConfigMap, false);
            if (actConfig != null) {
                long[] times = actConfig.getConfigTime(ActConfig.GROUP_ID_LOCAL, serverInfo.getStartTime(), curTime);
                response.setStartTime(times[0]);
                response.setEndTime(times[1]);
                response.setConfigId(actConfig.getConfigId());
            }
        } else {
            response.setActGroupId(ActConfig.GROUP_ID_GLOBAL);
            JsonObject param = RankActManager.isCrossRankAct(curTime);
            response.setStatus(2);
            if (null != param) { // 跨服活动
                String stimeDay = param.getString("stimeDay");
                long round = param.getLong("round");
                int configId = param.getInteger("actid");
                long stime = param.getLong("stime", 0L);
                long etime = param.getLong("etime");
                RankActGroup rankActGroup = RankActManager.getRankActGroup(serverInfo.getWarZone(), round);
                if (rankActGroup != null) {
                    JsonArray serverList = rankActGroup.getServerListArray();
                    if (Tool.isInList(serverList, userInfo.getServerId())) {
                        response.setStatus(1);
                        response.setConfigId(configId);
                    }
                }
                response.setStartTime(stime);
                response.setEndTime(etime);
            }
        }
        pbUserData.getActBuilder().setRankActTimeInfo(response);
    }

    public static ActConfig getActConfig(UserInfo userInfo, AtomicLong roundId) {
        int localDays = RankActManager.getActDays(ActConfig.GROUP_ID_LOCAL);
        long curTime = TimeUtils.getCurTime();
        int serverId = userInfo.getServerId();
        ServerInfo serverInfo = ServerManager.getServerInfo(serverId);
        int serverOpenDays = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        if (serverOpenDays <= localDays) { // 本服活动
            ConcurrentHashMap<Integer, ActConfig> actConfigMap = RankActManager.getActConfigList(ActConfig.GROUP_ID_LOCAL);
            ActConfig actConfig = RankActManager.getActConfig(serverOpenDays, actConfigMap, false);
            roundId.set(1);
            return actConfig;
        } else {
            JsonObject param = RankActManager.isCrossRankAct(curTime);
            if (null != param) {
                long round = param.getLong("round");
                roundId.set(round);
                int configId = param.getInteger("actid");
                if (isJoinCrossRankAct(serverInfo, round)) {
                    return RankActManager.getActConfig(configId);
                }
            }
        }
        return null;
    }

    public static boolean checkShopBuyLimit(UserInfo userInfo, ActConfig actConfig, long round, int num, Shop shop) {
        int shopId = shop.getId();
        long userId = userInfo.getId();
        if (actConfig.getGroupId() == ActConfig.GROUP_ID_LOCAL) {
            UserRankActShop userRankActShop = getUserRankActShop(userId, actConfig.getConfigId(), shopId);
            if (userRankActShop == null) {
                return num <= shop.getLimitNum();
            }
            if (userRankActShop.getNum() + num > shop.getLimitNum()) {
                return false;
            }
        } else {

        }
        return true;
    }

    public static ActConfig getRankActConfig(int serverId, long curTime, boolean isActLastDay) {
        ServerInfo server = ServerManager.getServerInfo(serverId);
        if (server != null && curTime >= TimeUtils.getStartTimeOfDay(server.getStartTime())) {
            int days = TimeUtils.getDiffDay(curTime, server.getStartTime())+1;//天数距离从第一天开始
            if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
                ConcurrentHashMap<Integer, ActConfig> configList = RankActManager.getActConfigList(ActConfig.GROUP_ID_LOCAL);
                if(configList != null) {
//                    System.out.println("configList: ");
//                    configList.values().stream().map(JsonObject::mapFrom).map(JsonObject::toString).forEach(System.out::println);
                    return getActConfig(days, configList, isActLastDay);
                }
                return null;
            }
            long crossActBeginTime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
            if (crossActBeginTime < curTime) {
                return null;
            }
            days = TimeUtils.getDiffDay(crossActBeginTime, curTime) + 1;
            ConcurrentHashMap<Integer, ActConfig> configList = RankActManager.getActConfigList(ActConfig.GROUP_ID_GLOBAL);
//						System.out.println("### 1 days:"+days);
            if(configList != null) {
                int allDays = getActDays(ActConfig.GROUP_ID_GLOBAL);
                if(days > allDays) {//超过天数，开始循环了
                    days %= allDays;//重新得到配置流的参数
//					System.out.println("### 2 days:"+days +" cycleLen:"+cycleLen);
                }
//				System.out.println("configList size = " + configList.size());
//                System.out.println("configList: ");
//                configList.values().stream().map(JsonObject::mapFrom).map(JsonObject::toString).forEach(System.out::println);
                return getActConfig(days, configList, isActLastDay);
            }
        }
        return null;
    }

    public static ActConfig getActConfig(int days, ConcurrentHashMap<Integer, ActConfig> configList, boolean isActLastDay) {
        if (configList == null) {
            return null;
        }
        for (Iterator<ActConfig> iter = configList.values().iterator(); iter.hasNext();) {
            ActConfig config = iter.next();
            if(isActLastDay) {//是否为活动最后一天，结算的时候是在最后一天
                if(days == config.getEndDay()) {
                    return config;
                }
            }else {
                if (days >= config.getStartDay()  && days <= config.getEndDay()  ) {
                    return config;
                }
            }
        }
        return null;
    }

    public static ActConfig getActConfigStartDay(int days, ConcurrentHashMap<Integer, ActConfig> configList) {
        for (Iterator<ActConfig> iter = configList.values().iterator(); iter.hasNext();) {
            ActConfig config = iter.next();
            if(days == config.getStartDay()) {
                return config;
            }
        }
        return null;
    }

    public static void addUserrank(int serverId, byte actRankType, UserInfo userInfo, double score, boolean isAdd) {
        if (score <= 0) {
            return;
        }
        long userId = userInfo.getId();
        long curTime = TimeUtils.getCurTime();
        ActConfig actConfig = getRankActConfig(serverId, curTime, false);
        if (actConfig != null) {
            ServerInfo serverinfo = ServerManager.getServerInfo(serverId);
            if (actConfig.getGroupId() == ActConfig.GROUP_ID_LOCAL) { // 本服活动
                ActTopRanking rankact = actConfig.getActTopRankingByType(actRankType); //根据子类型获取相应的冲榜活动
                if (rankact != null) {
                    long[] time = actConfig.getConfigTime(serverinfo.getWarZone(), serverinfo.getStartTime(), curTime);//获取活动的开始时间和结束时间
                    if (curTime > time[1]) {
                        return;
                    }
//                    long actStarttime = time[0]; //活动的开始时间
                    long round = 1;
                    long rankid = getRankId(actConfig.getConfigId(), actRankType);//由rankactconfig的configid和冲榜活动子类型组合出唯一值
                    UserActTopRank userrank = RankActManager.getUserActTopRank(userId, rankid);
                    if (userrank == null) { //生成新的数据
                        userrank = new UserActTopRank(userId, rankid, actRankType, score, round);
                        long initScore = getInitValue(userId, actRankType);
                        userrank.putInitScore(initScore);
                        userrank.doCreate();
                    } else {
                        if (userrank.getActTime() != round) { //活动时间不一样,新的活动,则重置分数
                            userrank.putActTime(round);
                            long initScore = getInitValue(userId, actRankType);
                            userrank.putInitScore(initScore);
                            userrank.putMaxScore(score);
                            userrank.putScore(score);
                        } else { //累加分数
                            if (isAdd) {
                                userrank.addScore(score);
                            } else {
                                userrank.putScore(score);
                            }
                        }
                    }
                    userrank.saveMaxScore();
                    userrank.update();
                    double curScore = ActTopRanking.isGetMaxScore(actRankType) ? userrank.getMaxScore() : userrank.getScore();
                    double rankScore = curScore - userrank.getInitScore();
                    String rankName = getServerActRankKey(rankid, serverId,round);
                    long oldRank = Future.await(RedisTools.getMyRank(rankName,String.valueOf(userId)));
//                    rankScore = RankManager.countScore((int)rankScore, curTime);//实际分数+时间戳
                    addRank(serverId, rankid, actRankType, userId, rankScore, round);//全量更新榜单
                    long newRank = Future.await(RedisTools.getMyRank(rankName,String.valueOf(userId)));
                    if (oldRank == 0 || newRank < oldRank) {
                        sendUserRankRedPoint(userId, actConfig.getConfigId(), actRankType, oldRank, newRank);
                    }
                }
            }
        }
    }

    public static void sendUserRankRedPoint(long userId, int groupId, int type, long oldRank, long newRank) {
        UserInfo userInfo = GameUser.getUserInfo(userId);
//        UserExtInfo userExtInfo = GameUser.getUserExtInfo(userId);
        GameUser.sendRedPointPrompt(userInfo, null, SystemConstant.RED_POINT_RANKACT_RISE, groupId, type, oldRank, newRank);
    }

    public static void addUnionRank(UserInfo userInfo,  byte actRankType, double score, boolean isAdd) {
        if (score <= 0) {
            return;
        }
//        long userId = userInfo.getId();
        UserUnion userUnion = UnionManager.getUserUnion(userInfo.getId());
        if (userUnion.getUnionId() == 0) {
            return;
        }
        UnionInfo unionInfo = UnionManager.getUnionInfo(userUnion.getUnionId());
        if (unionInfo == null) {
            return;
        }
        int serverId = userInfo.getServerId();
        long unionId = userUnion.getUnionId();
        long curTime = TimeUtils.getCurTime();
        Lock lock = null;
        try {
            lock = MainService.getVertLock(LockKey.getUnionRankActLock(unionId, actRankType));

            ActConfig actConfig = getRankActConfig(serverId, curTime, false);
            if (actConfig != null) {
                ServerInfo serverinfo = ServerManager.getServerInfo(serverId);
                if (actConfig.getGroupId() == ActConfig.GROUP_ID_LOCAL) { // 本服活动
                    ActTopRanking rankact = actConfig.getActTopRankingByType(actRankType); //根据子类型获取相应的冲榜活动
                    if (rankact != null) {
                        long[] time = actConfig.getConfigTime(serverinfo.getWarZone(), serverinfo.getStartTime(), curTime);//获取活动的开始时间和结束时间
                        if (curTime > time[1]) {
                            return;
                        }
//                    long actStarttime = time[0]; //活动的开始时间
                        long round = 1;
                        long rankid = getRankId(actConfig.getConfigId(), actRankType);//由rankactconfig的configid和冲榜活动子类型组合出唯一值
                        UnionActTopRank unionRank = RankActManager.getUnionActTopRank(unionId, rankid);
                        if (unionRank == null) { //生成新的数据
                            unionRank = new UnionActTopRank(unionId, rankid, actRankType, score, round);
                            unionRank.putInitScore(getInitValue(unionId, actRankType));
                            unionRank.doCreate();
                        } else {
                            if (unionRank.getActTime() != round) { //活动时间不一样,新的活动,则重置分数
                                unionRank.putActTime(round);
                                unionRank.putInitScore(getInitValue(unionId, actRankType));
                                unionRank.putMaxScore(score);
                                unionRank.putScore(score);
                            } else { //累加分数
                                if (isAdd) {
                                    unionRank.addScore(score);
                                } else {
                                    unionRank.putScore(score);
                                }
                            }
                        }
                        unionRank.saveMaxScore();
                        unionRank.update();
                        double rankScore = unionRank.getScore() - unionRank.getInitScore();
                        String rankName = getServerActRankKey(rankid, serverId,round);
                        long oldRank = Future.await(RedisTools.getMyRank(rankName,String.valueOf(unionId)));
//                    rankScore = RankManager.countScore((int)rankScore, curTime);//实际分数+时间戳
                        addRank(serverId, rankid, actRankType, unionId, rankScore, round);//全量更新榜单
                        long newRank = Future.await(RedisTools.getMyRank(rankName,String.valueOf(unionId)));
                        if (oldRank == 0 || newRank < oldRank) {
                            sendUnionRankRedPoint(unionId, actConfig.getConfigId(), actRankType, oldRank, newRank);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("addUnionRankError", e);
        } finally {
            MainService.releaseVertLock(lock);
        }
    }

    public static void sendUnionRankRedPoint(long unionId, int groupId, int type, long oldRank, long newRank) {
        JsonArray memberIds = UnionManager.getUnionMemberIdList(unionId);
        for (int i = 0; i < memberIds.size(); i++) {
            long memberId = Long.parseLong(memberIds.getString(i));
            UserInfo memberInfo = GameUser.getUserInfo(memberId);
            if (memberInfo != null) {
                GameUser.sendRedPointPrompt(memberInfo, null, SystemConstant.RED_POINT_RANKACT_RISE, groupId, type, oldRank, newRank);
            }
        }
    }

    public static long getRankId(int configId,byte actRankType) {
        return configId*100+actRankType;//支持最大99种榜单
    }

    public static boolean isScoreByTime(int subtype) {
        if (subtype == ActTopRanking.RANK_TYPE_EARN || subtype == ActTopRanking.RANK_TYPE_CHILD_EARN || subtype ==  ActTopRanking.RANK_TYPE_STAGE || subtype == ActTopRanking.RANK_TYPE_SECR_LIKE) {
            return true;
        }
        return false;
    }

    public static void addRank(int serverId, long rankId, int subtype, long userId, double score, long round){
        String rankName = getServerActRankKey(rankId, serverId,round);
        if (isScoreByTime(subtype)) {
            score = RankManager.getTimeScore((long)score, TimeUtils.getCurTime());//实际分数+时间戳
        }
        RedisTools.addRank(rankName, userId, score);
    }

    public static final String getServerActRankKey(long rankId,int serverId,long round){
        return "actrank.s"+serverId+"."+round+"."+rankId;
    }

    // 全服排行榜结算
    public static void runCrossRankReward() {
        logger.info("### runCrossRankReward start");
        Map<Integer, ServerInfo> serverInfoMap = ServerManager.getServerList();
        List<Integer> groupList = new ArrayList<>();
        for (ServerInfo serverInfo : serverInfoMap.values()) {
            if (serverInfo.getWarZone() == 0) {
                continue;
            }
            if (groupList.contains(serverInfo.getWarZone())) {
                continue;
            }
            groupList.add(serverInfo.getWarZone());
        }
        long curTime = TimeUtils.getCurTime();
//        long yesterday = curTime - TimeUtils.DAY;
        JsonObject actParam = isCrossRankAct(curTime);
        if (actParam != null && curTime >= actParam.getLong("etime")) {
            for (Integer groupId : groupList) {
                JsonObject param = new JsonObject(actParam.toString());
                param.put("groupId", groupId);
                runCrossRankReward(param);
//                TimedTaskManager.sendWorkTask(TimeTaskCmd.WORK_CROSS_RANK_ACT_TASK_REWARD, param);
            }
        }
    }

    // 获取结算活动
    public static ActConfig getActConfigEndDay(int days, int groupId) {
        ConcurrentHashMap<Integer, ActConfig> actConfigMap = getActConfigList(groupId);
        if (actConfigMap == null) {
            return null;
        }
        int totalDays = getActDays(groupId);
        days %= totalDays;
        days -= 1;
        if (days <= 0) {
            days += totalDays;
        }
        return getActConfig(days, actConfigMap, true);
    }

    public static void runCrossRankReward(JsonObject param) {
        logger.info("### runCrossRankReward param: " + param);
        try {
            int groupId = param.getInteger("groupId", 0);
            if (groupId == 0) {
                return;
            }
            String rankTime = param.getString("stimeDay");
            long round = param.getLong("round");
            long curTime = TimeUtils.getCurTime();
            long crossActBeginTime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
            if (crossActBeginTime > curTime) {
                return;
            }
            int days = TimeUtils.getDiffDay(crossActBeginTime, curTime) + 1;
            if (days <= 1) {
                return;
            }
            ActConfig actConfig = getActConfigEndDay(days, ActConfig.GROUP_ID_GLOBAL);
            if (actConfig == null) { // 结算时要判断前一天是否活动最后一天，如果不是最后一天返回的配置是空的
                return;
            }
//            long round = param.getLong("round");
            List<ActTopRanking> topRankingList = getActTopRankingList(actConfig.getRankList());
            for (ActTopRanking actTopRanking : topRankingList) {
                long rankId = getRankId(actConfig.getConfigId(), (byte) actTopRanking.getType());
                String userRankName = getCrossUserRankKey(rankId, groupId,round);
//                String rankKey = RedisKey.getCrossRankActKey(groupId, rankId);
                JsonArray rankList = Future.await(RedisTools.getRankListByIndex(userRankName, 0, actTopRanking.getList() - 1, false));
//                int type = actTopRanking.getType();
                logger.info("### runCrossRankReward groupId={}, rankId={}, size={}", groupId, rankId, rankList.size());
                if (!rankList.isEmpty()) {
                    for (int i = 0; i < rankList.size(); i++) {
                        int rank = i+1;
                        RankReward rankReward = RankManager.getRankReward(actTopRanking.getReward(), rank);
                        if (rankReward != null) {
                            long userId = rankList.getLong(i);
                            UserActTopCrossRank userActTopCrossRank = RankActManager.getUserActTopCrossRank(userId, actTopRanking.getType(), round);
                            if (userActTopCrossRank == null) {
                                userActTopCrossRank = new UserActTopCrossRank(userId, actTopRanking.getType(), round, 0);
                                userActTopCrossRank.doCreate();
                            }
                            if (userActTopCrossRank.getActTime() != round) {
                                continue;
                            }
                            List<RewardItem> rewardItemList = CommonUtils.takeReawrdItemFromStr(rankReward.getReward());// 奖励
                            MailManager.sendSystemMailReplaceContent(userId, actTopRanking.getWordTitle(),
                                    actTopRanking.getWordContent(), rewardItemList, LogType.RANK_ACT_CROSS_RANK_REWARD, rank);
                            userActTopCrossRank.putRankGet(1);
                            userActTopCrossRank.update();
                        }
                    }
                }
                RedisTools.expire(userRankName, TimeUtils.DAY * 7);
            }
        } catch (Exception e) {
            logger.error("### runCrossRankReward error, param: " + param, e);
        }
    }

    // 获取结算活动
    public static ActConfig getActConfigStartDay(int days, int groupId) {
        ConcurrentHashMap<Integer, ActConfig> actConfigMap = getActConfigList(groupId);
        if (actConfigMap == null) {
            return null;
        }
        int totalDays = getActDays(groupId);
        days %= totalDays;
        if (days <= 0) {
            days += totalDays;
        }
        return getActConfigStartDay(days, actConfigMap);
    }

    public static void matchCrossRankAct() {
        logger.info("### matchCrossRankAct start");

        try {
            long curDay = TimeUtils.getStartTimeOfDay(TimeUtils.getCurTime());
            long nextDay = curDay + TimeUtils.DAY;
//            System.out.println("tomorrow: " + nextDay);
            JsonObject nextActInfo = isCrossRankAct(nextDay);
//            System.out.println("nextActInfo: " + nextActInfo);
            if (nextActInfo != null && nextDay == nextActInfo.getLong("stime", 0L)) {
                Map<Integer, ServerInfo> serverInfoMap = ServerManager.getServerList();
                List<Integer> groupList = new ArrayList<>();
                for (ServerInfo serverInfo : serverInfoMap.values()) {
                    if (serverInfo.getWarZone() == 0) {
                        continue;
                    }
                    if (groupList.contains(serverInfo.getWarZone())) {
                        continue;
                    }
                    groupList.add(serverInfo.getWarZone());
                }
                for (Integer groupId : groupList) {
                    JsonObject param = new JsonObject(nextActInfo.toString());
                    param.put("groupId", groupId);
                    matchCrossRankAct(param);
//                    TimedTaskManager.sendWorkTask(TimeTaskCmd.WORK_CROSS_RANK_ACT_MATCH, param);
                }
            }
        } catch (Exception e) {
            logger.error("### matchCrossRankAct error.", e);
        }
    }

    public static void matchCrossRankAct(JsonObject param) {
        logger.info("### matchNewAct start, param: " + param);
        try {
            String rankactTime = param.getString("stimeDay");
            long round = param.getLong("round");
            int groupId = param.getInteger("groupId", 0);
            if (groupId == 0) {
                return;
            }

            long stime = param.getLong("stime", 0L);
            long crossActBeginTime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
            int days = TimeUtils.getDiffDay(crossActBeginTime, stime) + 1;
//            ConcurrentHashMap<Integer, ActConfig> actConfigMap = getActConfigList(ActConfig.GROUP_ID_GLOBAL);
//            if (actConfigMap == null) {
//                return;
//            }
            ActConfig actConfig = getActConfigStartDay(days, ActConfig.GROUP_ID_GLOBAL);
            if (actConfig == null) {
                return;
            }

            JsonArray serverIdList = ServerManager.getServerIdListByWarZone(groupId);// 根据战区分组id,获取该战区的所有服务器
            if (serverIdList == null || serverIdList.isEmpty()) {
                return;
            }

            List<ActTopRanking> rankingList = getActTopRankingList(actConfig.getRankList());
            RankActGroup rankActGroup = getRankActGroup(groupId, round);
            if (rankActGroup == null) {
                rankActGroup = new RankActGroup(groupId, round);
                rankActGroup.doCreate();
            }
            int localActDays = getActDays(ActConfig.GROUP_ID_LOCAL);

            JsonArray serverIdArray = new JsonArray();

            for (int i=0; i<serverIdList.size(); i++) {
                int sid = serverIdList.getInteger(i);
                ServerInfo serverInfo = ServerManager.getServerInfo(sid);
                if (serverInfo.getStartTime() > stime) { // 未开服
                    continue;
                }
                if (TimeUtils.getDiffDay(serverInfo.getStartTime() + TimeUtils.DAY) + 1 < localActDays) { // 到明天本服活动还没结束
                    continue;
                }
                serverIdArray.add(sid);
            }
            if (!serverIdArray.isEmpty()) {
                rankActGroup.putServerList(serverIdArray.toString());
                rankActGroup.updateQueueNow();
                logger.info("### matchNewAct start, actGroup={}, configId={}, serverIdArray={}", rankActGroup.getRankId(), rankActGroup.getRound(), serverIdArray);
            }
        } catch (Exception e) {
            logger.error("### matchNewAct error, param: " + param, e);
        }
    }

    /**
     * 根据传入的时间 计算跨服冲榜活动的周期
     */
    public static JsonObject isCrossRankAct (long curtime) {
        //配置了开始时间 结束时间为0 代表会自动循环 默认不结束
        //配置了开始时间 和结束时间，且当前时间小于结束时间，默认活动会继续跑 直到结束时间
        //配置了开始时间 和结束时间  但是当前时间已经大于结束时间，默认不开启活动. 就算开始时间配置的是有效时间
        //总结:结束时间有配置 优先级会比开始时间高，比如因为配置表需要调整 关闭之后 在配置新的一期的话 开始时间修改的话 结束时间也要改
        long stime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
        //开始时间配置诶0 默认不开启活动 ||  配置结束时间 并且 当前时间 大于 结束时间
        if (stime > curtime ) {
            //跨服冲榜活动不开启
            return null;
        }

        //计算传入时间的跨服冲榜活动时间
        ConcurrentHashMap<Integer, ActConfig> actMap = getActConfigList(ActConfig.GROUP_ID_GLOBAL);
        if (actMap == null) {
            return null;
        }
        List<ActConfig> actList = new ArrayList<>(actMap.values());
        actList.sort(Comparator.comparing(ActConfig::getStartDay));
        int CROSS_RANKACT_DAYNUM = getActDays(ActConfig.GROUP_ID_GLOBAL);
        int diffDay = TimeUtils.getDiffDay(curtime,stime);//两个时间相差天数
        int actPeriod = diffDay / CROSS_RANKACT_DAYNUM + 1;//活动当前期数
        int actPeriodDay = diffDay % CROSS_RANKACT_DAYNUM;//活动当前天数
        int curAcDay = actPeriodDay + 1;
        if (curAcDay > CROSS_RANKACT_DAYNUM) {
            curAcDay -= CROSS_RANKACT_DAYNUM;
        }

        ActConfig currAct = getActConfig(curAcDay, actMap, false);
        if (currAct == null) {
            return null;
        }
        //计算当前活动信息
        int crossRankActId = currAct.getConfigId();
        long curActStime = stime + (diffDay - actPeriodDay + currAct.getStartDay() - 1) * TimeUtils.DAY;
        long curActEtime = curActStime + (currAct.getEndDay() + 1 - currAct.getStartDay()) * TimeUtils.DAY - 2 * TimeUtils.HOUR;//22点结束
        long curActClosetime = curActStime + (currAct.getEndDay() + 1 - currAct.getStartDay()) * TimeUtils.DAY + 22 * TimeUtils.HOUR;
//        System.out.println("curtime=" + TimeUtils.getTimeFullStr(curtime) + ", diffDay = " + diffDay + ", CROSS_RANKACT_DAYNUM=" + CROSS_RANKACT_DAYNUM);
        if (diffDay % CROSS_RANKACT_DAYNUM != 0) {
            actPeriod += 1;
        }

        JsonObject result = new JsonObject();
        result.put("actid",crossRankActId);//活动id
        result.put("stime",curActStime);//活动开始时间
        result.put("stimeDay",TimeUtils.getDayStr(curActStime));//活动开始时间
        result.put("etime",curActEtime);//结束时间
        result.put("closetime",curActClosetime);//活动关闭时间
        result.put("round", actPeriod); // 当前轮次
        result.put("actDay", actPeriodDay); // 当前天数
        return result;
    }

    /**
     * 本服结算
     */
    public static void doRankActReward() {
        logger.info("### doRankActReward start");
        try {
            long yesterday = TimeUtils.getCurTime() - TimeUtils.DAY;

            ConcurrentHashMap<Integer, ServerInfo> serverList = ServerManager.getServerList();
            for (ServerInfo serverInfo : serverList.values()) {
                if (!serverInfo.isMerged() && yesterday > serverInfo.getStartTime()) {
                    ActConfig actConfig = getRankActConfig(serverInfo.getServerId(), yesterday, true);
                    if (actConfig != null) {
                        long[] times = actConfig.getConfigTime(serverInfo.getWarZone(), serverInfo.getStartTime(), yesterday);
                        JsonObject param = new JsonObject();
                        param.put("stime", times[0]);
//                        param.put("etime", times[1]);
                        param.put("configId", actConfig.getConfigId());
                        param.put("serverId", serverInfo.getServerId());
                        sendRankReward(param);
//                        TimedTaskManager.sendWorkTask(TimeTaskCmd.RANK_ACT_TASK_REWARD, param);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("### doRankActReward error", e);
        }
    }

    public static void sendRankReward(JsonObject rankObj) {
        logger.info("### sendRankReward begins, rankObj: " + rankObj);
        try {
            long stime = rankObj.getLong("stime");
//            long etime = rankObj.getLong("etime");
            int configId = rankObj.getInteger("configId");
            int serverId = rankObj.getInteger("serverId");
//            long curTime = rankObj.getLong("curTime");
            ServerInfo server = ServerManager.getServerInfo(serverId);
            ActConfig config = getActConfig(configId);
//            long[] time = config.getConfigTime(server.getActGroup(), server.getStartTime(), curTime);
            long round = 1;
            List<ActTopRanking> topRankingList = getActTopRankingList(config.getRankList());
            for (ActTopRanking ranking : topRankingList) {
                String rankName = RankActManager.getServerActRankKey(RankActManager.getRankId(configId, (byte) ranking.getType()), server.getServerId(), round);
                JsonArray rankList = Future.await(RedisTools.getRankListByIndex(rankName, 0, ranking.getList() - 1, false));
                long actId = getRankId(configId, (byte) ranking.getType());
                int type = ranking.getType();
                for (int i=0; i<rankList.size(); i++) {
                    int rank = i+1;
                    long uid = Long.parseLong(rankList.getString(i)); //用户Id
                    if (type == ActTopRanking.RANK_TYPE_UNION_EXP) {
                        UnionInfo unionInfo = UnionManager.getUnionInfo(uid);
                        if (unionInfo == null) {
                            continue;
                        }
                        List<UnionMember> unionMemberList = UnionManager.getUnionMemberList(uid);
                        for (UnionMember unionMember : unionMemberList) {
                            boolean isMember = unionMember.getUserId() != unionInfo.getMasterId();
                            sendUnionRankReward(rank, unionMember.getUserId(), actId, ranking.getReward(), ranking.getWordTitle(), ranking.getWordContent(), isMember);
                        }
                    } else {
                        sendUserRankReward(rank, uid, actId, ranking.getReward(), ranking.getWordTitle(), ranking.getWordContent(), false);
                    }
//                    UserActTopRank userActTopRank = getUserActTopRank(uid, actId);
//                    if (userActTopRank != null && userActTopRank.getRankGet() == 0) {
//                        RankReward rankReward = RankManager.getRankReward(ranking.getReward(), rank);
//                        List<RewardItem> rewardItemList = CommonUtils.takeReawrdItemFromStr(rankReward.getReward());// 奖励
//                        MailManager.sendSystemMailReplaceContent(uid, MailConstant.getRankActRewardTitleByType(type),
//                                MailConstant.getRankActRewardContentByType(type), rewardItemList,
//                                LogType.RANK_ACT_RANK_REWARD, rank);
//                        userActTopRank.putRankGet(1);
//                        userActTopRank.update();
//                    }
                }
            }
        } catch (Exception e) {
            logger.error("### sendRankReward error", e);
        }
    }

    public static void sendUserRankReward(int rank, long uid, long actId, int rankType, int worldTitle, int worldContent, boolean isMember) {
        UserActTopRank userActTopRank = getUserActTopRank(uid, actId);
        if (userActTopRank != null && userActTopRank.getRankGet() == 0) {
            RankReward rankReward = RankManager.getRankReward(rankType, rank);
            if (rankReward == null) {
                return;
            }
            List<RewardItem> rewardItemList = isMember ? CommonUtils.takeReawrdItemFromStr(rankReward.getReward2()) : CommonUtils.takeReawrdItemFromStr(rankReward.getReward());// 奖励
            MailManager.sendSystemMailReplaceContent(uid, worldTitle, worldContent, rewardItemList,
                    LogType.RANK_ACT_RANK_REWARD, rank);
            userActTopRank.putRankGet(1);
            userActTopRank.update();
        }
    }
    public static void sendUnionRankReward(int rank, long uid, long actId, int rankType, int worldTitle, int worldContent, boolean isMember) {
        UserActTopRank userActTopRank = getUserActTopRank(uid, actId);
        if (userActTopRank == null) {
            userActTopRank = new UserActTopRank(uid, actId, (byte) rankType, 0, 1);
            userActTopRank.doCreate();
        }
        if (userActTopRank.getRankGet() == 0) {
            RankReward rankReward = RankManager.getRankReward(rankType, rank);
            if (rankReward == null) {
                return;
            }
            List<RewardItem> rewardItemList = isMember ? CommonUtils.takeReawrdItemFromStr(rankReward.getReward2()) : CommonUtils.takeReawrdItemFromStr(rankReward.getReward());// 奖励
            MailManager.sendSystemMailReplaceContent(uid, worldTitle, worldContent, rewardItemList,
                    LogType.RANK_ACT_RANK_REWARD, rank);
            userActTopRank.putRankGet(1);
            userActTopRank.update();
        }
    }

    /**
     * 更新玩家开服冲榜数据
     */
    public static void addUserCrossRank(UserInfo userInfo,int serverId,int rankType, double addScore, boolean isAdd) {
        long userId = userInfo.getId();
        long curTime = TimeUtils.getCurTime();
        ConcurrentHashMap<Integer, ActConfig> actConfigMap = getActConfigList(ActConfig.GROUP_ID_GLOBAL);
        if (actConfigMap == null || actConfigMap.isEmpty()) {
            return;
        }
        ServerInfo serverInfo = ServerManager.getServerInfo(serverId);
        long crossActBeginTime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
        int days = TimeUtils.getDiffDay(crossActBeginTime, curTime) + 1;
        int totalDays = getActDays(ActConfig.GROUP_ID_GLOBAL);
        days = days % totalDays + 1;
        ActConfig actConfig = getActConfig(days, actConfigMap, false);
        if (actConfig == null) {
            return;
        }

        JsonObject actInfo = RankActManager.isCrossRankAct(curTime);
        if (actInfo == null) {
            return ;
        }
        long stime = actInfo.getLong("stime");
        long etime = actInfo.getLong("etime");
        int closetime = actInfo.getInteger("closetime");
        int actid = actInfo.getInteger("actid");
        String rankTime = actInfo.getString("stimeDay");
        long round = actInfo.getLong("round");
        if (!isJoinCrossRankAct(serverInfo, round)) {
            return;
        }
        ActConfig nextCross_rank_act = getActConfig(actid);
        List<ActTopRanking> rankingList = getActTopRankingList(nextCross_rank_act.getRankList());
        JsonArray ranklist = new JsonArray();
        if (rankingList != null && !rankingList.isEmpty()) {
            rankingList.stream().map(ActTopRanking::getType).forEach(ranklist::add);
        }

        long rankId = getRankId(actid, (byte) rankType);
        if (!ranklist.contains(rankType) || curTime < stime || curTime > etime) { // 活动结束前两个小时结算
            return;
        }
        UserActTopCrossRank usercrossrank = getUserActTopCrossRank(userId,rankId, round);
        if (usercrossrank == null) { //生成新的数据
            usercrossrank = new UserActTopCrossRank(userId, rankId, round,addScore);
            long initScore = getInitValue(userId, rankType);
            usercrossrank.putInitScore(initScore);
            usercrossrank.doCreate();
        } else {
            if (usercrossrank.getActTime() != round) { //活动时间不一样,新的活动,则重置分数
                usercrossrank.putActTime(round);
                usercrossrank.putInitScore(getInitValue(userId, rankType));
                usercrossrank.putMaxScore(addScore);
                usercrossrank.putScore(addScore);
            } else { //累加分数
                if (isAdd) {
                    usercrossrank.addScore(addScore);
                } else {
                    usercrossrank.putScore(addScore);
                }
            }
            usercrossrank.update();
        }
        usercrossrank.saveMaxScore();
        int groupId = serverInfo.getWarZone();
        //获取我的分数
//		double rankscore = RankManager.getMyScore(getCrossUserRankKey(rankId, groupId,rankTime), userId);
//		double scoreTotal = rankscore + addScore;
//		double rankscore = Cross_rank_config.getScore(rankId,usercrossrank.getScore());

        String userRankName = getCrossUserRankKey(rankId, groupId,round);
        double curScore = ActTopRanking.isGetMaxScore(rankType) ? usercrossrank.getMaxScore() : usercrossrank.getScore();
        double rankScore = curScore - usercrossrank.getInitScore();
//        result = RankManager.countScore((int)usercrossrank.getScore(), TimeUtils.getCurTime());//实际分数+时间戳
        double userRresult = RankManager.getTimeScore((long) rankScore, TimeUtils.getCurTime());//实际分数+时间戳


        long oldRank = Future.await(RedisTools.getMyRank(userRankName,String.valueOf(userId)));
        //更新个人榜单
        Future.await(RedisTools.addRank(userRankName, userId, userRresult));
        long newRank = Future.await(RedisTools.getMyRank(userRankName,String.valueOf(userId)));
        if (oldRank == 0 || newRank < oldRank) {
            sendUserRankRedPoint(userId, actConfig.getConfigId(), rankType, oldRank, newRank);
        }

        //更新跨服 全服数据
//        if (addScore > 0) {
//            String serverRankKey = getCrossServerRankKey(rankId, groupId,rankTime);
//            long serverResult = (long) addScore;//实际分数
//            RedisTools.updateRank(serverRankKey, serverId, serverResult);
//        }
    }

    public static void addUnionCrossRank(UserInfo userInfo,int rankType, double addScore, boolean isAdd) {
        long curTime = TimeUtils.getCurTime();
        ConcurrentHashMap<Integer, ActConfig> actConfigMap = getActConfigList(ActConfig.GROUP_ID_GLOBAL);
        if (actConfigMap == null || actConfigMap.isEmpty()) {
            return;
        }
        int serverId = userInfo.getServerId();
        ServerInfo serverInfo = ServerManager.getServerInfo(serverId);
        long crossActBeginTime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
        int days = TimeUtils.getDiffDay(crossActBeginTime, curTime);
        int totalDays = getActDays(ActConfig.GROUP_ID_GLOBAL);
        days = days % totalDays + 1;
        ActConfig actConfig = getActConfig(days, actConfigMap, false);
        if (actConfig == null) {
            return;
        }

        JsonObject actInfo = RankActManager.isCrossRankAct(curTime);
        if (actInfo == null) {
            return ;
        }
        long stime = actInfo.getLong("stime");
        long etime = actInfo.getLong("etime");
        int closetime = actInfo.getInteger("closetime");
        int actid = actInfo.getInteger("actid");
        String rankTime = actInfo.getString("stimeDay");
        long round = actInfo.getLong("round");
        if (!isJoinCrossRankAct(serverInfo, round)) {
            return;
        }
        ActConfig nextCross_rank_act = getActConfig(actid);
        List<ActTopRanking> rankingList = getActTopRankingList(nextCross_rank_act.getRankList());
        JsonArray ranklist = new JsonArray();
        if (rankingList != null && !rankingList.isEmpty()) {
            rankingList.stream().map(ActTopRanking::getType).forEach(ranklist::add);
        }

        long rankId = getRankId(actid, (byte) rankType);
        if (!ranklist.contains(rankType) || curTime < stime || curTime > etime) { // 活动结束前两个小时结算
            return;
        }
        UserUnion userUnion = UnionManager.getUserUnion(userInfo.getId());
        long unionId = userUnion.getUnionId();
        if (unionId == 0) {
            return;
        }
        UnionInfo unionInfo = UnionManager.getUnionInfo(unionId);
        if (unionInfo == null) {
            return;
        }
        Lock lock = null;
        try {
            lock = MainService.getVertLock(LockKey.getUnionCrossRankActLock(unionId, rankType));
            UnionActTopCrossRank unionRank = getUnionActTopCrossRank(unionId,rankId, round);
            if (unionRank == null) { //生成新的数据
                unionRank = new UnionActTopCrossRank(unionId, rankId, round,addScore);
                unionRank.putInitScore(getInitValue(unionId, rankType));
                unionRank.doCreate();
            } else {
                if (unionRank.getActTime() != round) { //活动时间不一样,新的活动,则重置分数
                    unionRank.putActTime(round);
                    unionRank.putInitScore(getInitValue(unionId, rankType));
                    unionRank.putMaxScore(addScore);
                    unionRank.putScore(addScore);
                } else { //累加分数
                    if (isAdd) {
                        unionRank.addScore(addScore);
                    } else {
                        unionRank.putScore(addScore);
                    }
                }
                unionRank.update();
            }
            unionRank.saveMaxScore();
            int groupId = serverInfo.getWarZone();
            //获取我的分数
//		double rankscore = RankManager.getMyScore(getCrossUserRankKey(rankId, groupId,rankTime), userId);
//		double scoreTotal = rankscore + addScore;
//		double rankscore = Cross_rank_config.getScore(rankId,usercrossrank.getScore());

            String userRankName = getCrossUserRankKey(rankId, groupId,round);
            double rankScore = unionRank.getScore() - unionRank.getInitScore();
//        result = RankManager.countScore((int)usercrossrank.getScore(), TimeUtils.getCurTime());//实际分数+时间戳
            double userRresult = RankManager.getTimeScore((long) rankScore, TimeUtils.getCurTime());//实际分数+时间戳


            long oldRank = Future.await(RedisTools.getMyRank(userRankName,String.valueOf(unionId)));
            //更新个人榜单
            Future.await(RedisTools.addRank(userRankName, unionId, userRresult));
            long newRank = Future.await(RedisTools.getMyRank(userRankName,String.valueOf(unionId)));
            if (oldRank == 0 || newRank < oldRank) {
                sendUnionRankRedPoint(unionId, actConfig.getConfigId(), rankType, oldRank, newRank);
            }
        } catch (Exception e) {
            logger.error("addUnionCrossRankError", e);
        } finally {
            MainService.releaseVertLock(lock);
        }

        //更新跨服 全服数据
//        if (addScore > 0) {
//            String serverRankKey = getCrossServerRankKey(rankId, groupId,rankTime);
//            long serverResult = (long) addScore;//实际分数
//            RedisTools.updateRank(serverRankKey, serverId, serverResult);
//        }
    }

    /**
     * 获取跨服冲榜服务器分组信息 分组key
     */
    public static String getHashGroupKey(int groupid) {
        return "g." + groupid;
    }

    /**
     * 获取跨服冲榜服务器分组信息 服务器key
     */
    public static String getHashServerKey(int serverid) {
        return "s." + serverid;
    }

    /***
     * 获取跨服排行榜的key名
     * @param rankId 榜单id
     * @param groupId 分组id
     * @return
     */
    public static final String getCrossUserRankKey(long rankId,int groupId, long round){
        return "cross.rank.user.g"+groupId+"."+rankId+"."+round;
    }

    /***
     * 获取跨服排行榜的key名
     * @param rankId 榜单id
     * @param groupId 分组id
     * @return
     */
    public static final String getCrossServerRankKey(int rankId,int groupId,String dateStr){
        return "cross.rank.server.g"+groupId+"."+rankId+"."+dateStr;
    }

    /**
     * 获取排行榜数据
     * @param userId
     * @param score
     * @return
     */
    public static PBRankMember.Builder getRankMember(long userId, double score) {
        PBRankMember.Builder rankMember = PBRankMember.newBuilder();
        UserShow userShow = GameUser.getUserShow(userId);
        rankMember.setUserShow(userShow.takeInitBuilder());
        rankMember.setUserId(userId);
        rankMember.setScore((long) score);

        return rankMember;
    }

    public static PBRankMember.Builder getUnionRankMember(long unionId, double score) {
        PBRankMember.Builder rankMember = PBRankMember.newBuilder();
        rankMember.setUserId(unionId);
        rankMember.setScore((long) score);
        UnionInfo unionInfo = UnionManager.getUnionInfo(unionId);
        if (unionInfo != null) {
            rankMember.setUnionName(unionInfo.getName());
            rankMember.setUnionLevel(unionInfo.getLevel());
            rankMember.setUnionIcon(unionInfo.getIcon());
        }
        return rankMember;
    }

    public static void updateUserRank(UserInfo userInfo) {
        long userId = userInfo.getId();
        UserPower userPower = GameUser.getUserPower(userId);
        addUserrank(userInfo.getServerId(), ActTopRanking.RANK_TYPE_EARN, userInfo, userPower.getEarn(), false);
        addUserCrossRank(userInfo, userInfo.getServerId(), ActTopRanking.RANK_TYPE_EARN, userPower.getEarn(), false);

        UserStage userStage = FightManager.getUserStage(userId);
        long stageProgress = userStage.getStageProgress();
        addUserrank(userInfo.getServerId(), ActTopRanking.RANK_TYPE_STAGE, userInfo, stageProgress, false);
        addUserCrossRank(userInfo, userInfo.getServerId(), ActTopRanking.RANK_TYPE_STAGE, stageProgress, false);

        addUserrank(userInfo.getServerId(), ActTopRanking.RANK_TYPE_CHILD_EARN, userInfo, userPower.getChildEarn(), false);
        addUserCrossRank(userInfo, userInfo.getServerId(), ActTopRanking.RANK_TYPE_CHILD_EARN, userPower.getChildEarn(), false);

        UserSnatchScore snatch = FightManager.getUserSnatchScore(userId);
        addUserrank(userInfo.getServerId(), ActTopRanking.RANK_TYPE_SNATCH_EARN, userInfo, snatch.getScore(), false);
        addUserCrossRank(userInfo, userInfo.getServerId(), ActTopRanking.RANK_TYPE_SNATCH_EARN, snatch.getScore(), false);

        addUserrank(userInfo.getServerId(), ActTopRanking.RANK_TYPE_PARTNER_POWER, userInfo, PartnerManager.getPartnerTotalPower(userId), false);
        addUserCrossRank(userInfo, userInfo.getServerId(), ActTopRanking.RANK_TYPE_PARTNER_POWER, PartnerManager.getPartnerTotalPower(userId), false);
    }

    public static long getInitValue(long userId, int rankType) {
        return switch (rankType) {
            case ActTopRanking.RANK_TYPE_EARN -> {
                UserPower power = GameUser.getUserPower(userId);
                yield power.getEarn();
            }
            case ActTopRanking.RANK_TYPE_CHILD_EARN -> {
                UserPower power = GameUser.getUserPower(userId);
                yield power.getChildEarn();
            }
            case ActTopRanking.RANK_TYPE_SNATCH_EARN -> {
                UserSnatchScore snatch = FightManager.getUserSnatchScore(userId);
                yield snatch.getScore();
            }
            case ActTopRanking.RANK_TYPE_PARTNER_POWER -> PartnerManager.getPartnerTotalPower(userId);
            default -> 0;
        };
    }

    public static void updateTask(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, long num, int param, boolean isAdd) {
        int serverId = userInfo.getServerId();
        ServerInfo server = ServerManager.getServerInfo(serverId);
        long curTime = TimeUtils.getCurTime();
        if (curTime >= TimeUtils.getStartTimeOfDay(server.getStartTime())) {
            int days = TimeUtils.getDiffDay(curTime, server.getStartTime())+1;//天数距离从第一天开始
            if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
                ConcurrentHashMap<Integer, ActConfig> configList = RankActManager.getActConfigList(ActConfig.GROUP_ID_LOCAL);
                if(configList != null) {
                    ActConfig actConfig = getActConfig(days, configList, false);
                    long[] times =actConfig.getConfigTime(ActConfig.GROUP_ID_LOCAL, server.getStartTime(), curTime);
                    if (times == null) {
                        return;
                    }
                    int actDays = getActDays(ActConfig.GROUP_ID_LOCAL);
                    long round = days / actDays; // 第几轮
                    if (days % actDays != 0) {
                        round += 1;
                    }
                    int curActDay = days % actDays;
                    if (curActDay == 0) {
                        curActDay = actDays;
                    }
                    updateTask(pbUserData, userInfo, round, actConfig, taskType, curActDay, num, param, isAdd);
                }
            }
        }
    }

    private static void updateTask(PBUserData.Builder pbUserData, UserInfo userInfo, long round, ActConfig actConfig, int taskType, int day, long value, int param, boolean isAdd) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        int[] timeTaskArray = actConfig.getTimeTaskArray();
        List<ActTask> taskList = new ArrayList<>();
        for (int groupId : timeTaskArray) {
            List<ActTask> list = ActDaysManager.getRankActTasksByGroupId(groupId, taskType, param);
            if (list == null || list.isEmpty()) {
                continue;
            }
            taskList.addAll(list);
        }
        ActTask actTask = taskList.stream().min(Comparator.comparing(ActTask::getId)).orElse(null);
        if (actTask == null) {
            return;
        }
        boolean update = false;
        int taskId = ActDaysManager.getTaskId(taskType, param);
        UserRankActTask task = getUserRankActTask(userId, round, configId, taskId);
        long oldP = 0;
        if (task == null) {
            task = new UserRankActTask(userId, round, configId, taskId);
            task.putCurP(value);
            task.doCreate();
            ProtoDataUtils.updatePBUserData(pbUserData, task);
        } else {
            task.checkReset(round);
            oldP = task.getCurP();
            if (isAdd) {
                task.addCurP(value);
                update = true;
            } else {
                if (value > task.getCurP()) {
                    task.putCurP(value);
                    update = true;
                }
            }
        }
        if (update) {
            task.update();
            ProtoDataUtils.updatePBUserData(pbUserData, task);
            checkTaskRedPoint(userInfo, actConfig, oldP);
        }
    }

    public static void checkTaskRedPoint(UserInfo userInfo, ActConfig actConfig, long oldP) {
        boolean isRedPoint = false;
        UserRankAct userRankAct = getUserRankAct(userInfo.getId(), 1, actConfig.getConfigId());
        if (userRankAct == null) {
            return;
        }
        // 限时任务
        List<UserRankActTask> userTaskList = getUserRankActTaskList(userInfo.getId(), 1, actConfig.getConfigId());
        ConcurrentHashMap<Integer, UserRankActTask> taskMap = new ConcurrentHashMap<>();
        for (UserRankActTask task : userTaskList) {
            taskMap.put(task.getTaskType(), task);
        }
        CsGameSystem.RedPoint_RankactReward.Builder redPoint = CsGameSystem.RedPoint_RankactReward.newBuilder();
        int[] taskList = actConfig.getTimeTaskArray();
        JsonArray taskGet = userRankAct.getTaskGetArray();
        List<Integer> taskIdList = new ArrayList<>();
        for (int taskGroup : taskList) {
            List<ActTask> actTasks = ActDaysManager.getActTasksByGroupId(taskGroup);
            for (ActTask task : actTasks) {
                UserRankActTask userTask = taskMap.getOrDefault(task.getTaskType(), null);
                if (userTask == null) {
                    continue;
                }
                if (taskGet.contains(userTask.getId())) {
                    continue;
                }
                if (oldP < task.getNum1() && userTask.getCurP() >= task.getNum1()) {
                    taskIdList.add(taskGroup);
                    isRedPoint = true;
                    break;
                }
            }
        }
        if (isRedPoint) {
            GameUser.sendRedPointPrompt(userInfo, null, SystemConstant.RED_POINT_RANKACT_RED_POINT, SystemConstant.RED_POINT_RANKACT_SUB_TYPE_TASK, actConfig.getConfigId(), taskIdList);
        }
    }

    public static void addRankActTask(PBUserData.Builder pbUserData, UserInfo userInfo,  int taskType, long num, Object... params) {
        int param = 0;
        if (params.length > 0) {
            param = (int) params[0];
        }
        updateTask(pbUserData, userInfo, taskType, num, param, true);
    }
    public static void updateRankActTask(PBUserData.Builder pbUserData, UserInfo userInfo,  int taskType, long num, Object... params) {
        int param = 0;
        if (params.length > 1) {
            param = (int) params[0];
        }
        updateTask(pbUserData, userInfo, taskType, num, param, false);
    }

    public static void addTaskProgress(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, long num, Object... params) {
        addRankActTask(pbUserData, userInfo, taskType, num, params);
        addCrossRankActTask(pbUserData, userInfo, taskType, num, params);
    }
    public static void updateTaskProgress(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, long num, Object... params) {
        updateRankActTask(pbUserData, userInfo, taskType, num, params);
        updateCrossRankActTask(pbUserData, userInfo, taskType, num, params);
    }

    public static void addCrossRankActTask(PBUserData.Builder pbUserData, UserInfo userInfo,  int taskType, long num, Object... params) {
        int param = 0;
        if (params.length > 0) {
            param = (int) params[0];
        }
        updateCrossTask(pbUserData, userInfo, taskType, num, param, true);
    }
    public static void updateCrossRankActTask(PBUserData.Builder pbUserData, UserInfo userInfo,  int taskType, long num, Object... params) {
        int param = 0;
        if (params.length > 0) {
            param = (int) params[0];
        }
        updateCrossTask(pbUserData, userInfo, taskType, num, param, false);
    }

    public static void updateCrossTask(PBUserData.Builder pbUserData, UserInfo userInfo,  int taskType, long num, int param, boolean isAdd) {
        int serverId = userInfo.getServerId();
        ServerInfo server = ServerManager.getServerInfo(serverId);
        long curTime = TimeUtils.getCurTime();
        if (curTime >= TimeUtils.getStartTimeOfDay(server.getStartTime())) {
            int days = TimeUtils.getDiffDay(curTime, server.getStartTime())+1;
            if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
                return;
            }
            JsonObject actParam = isCrossRankAct(curTime);
            if (actParam == null) {
                return;
            }
            long round = actParam.getLong("round");
            int configId = actParam.getInteger("actid");
            int actDay = actParam.getInteger("actDay") + 1;
            if (!isJoinCrossRankAct(server, round)) {
                return;
            }
            ActConfig actConfig = RankActManager.getActConfig(configId);
            if (actConfig == null) {
                return;
            }
            updateCrossTask(pbUserData, userInfo, round, actConfig, actDay, taskType, num, param, isAdd);
        }
    }

    public static void updateCrossTask(PBUserData.Builder pbUserData, UserInfo userInfo, long round, ActConfig actConfig, int day, int taskType, long value, int param, boolean isAdd) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        int[] timeTaskArray = actConfig.getTimeTaskArray();
        List<ActTask> taskList = new ArrayList<>();
        for (int groupId : timeTaskArray) {
            List<ActTask> list = ActDaysManager.getRankActTasksByGroupId(groupId, taskType, param);
            if (list == null || list.isEmpty()) {
                continue;
            }
            taskList.addAll(list);
        }
        ActTask actTask = taskList.stream().min(Comparator.comparing(ActTask::getId)).orElse(null);
        if (actTask == null) {
            return;
        }

        boolean update = false;
        int taskId = ActDaysManager.getTaskId(taskType, param);
        UserCrossRankActTask task = getUserCrossRankActTask(userId, round, configId, taskId);
        long oldP = 0;
        if (task == null) {
            task = new UserCrossRankActTask(userId, round, configId, taskId);
            task.putCurP(value);
            task.doCreate();
            ProtoDataUtils.updatePBUserData(pbUserData, task);
        } else {
            oldP = task.getCurP();
            if (isAdd) {
                task.addCurP(value);
                update = true;
            } else {
                if (value > task.getCurP()) {
                    task.putCurP(value);
                    update = true;
                }
            }
        }
        if (update) {
            task.update();
            ProtoDataUtils.updatePBUserData(pbUserData, task);
            checkCrossTaskRedPoint(userInfo, actConfig, round, oldP);
        }
    }

    public static void checkCrossTaskRedPoint(UserInfo userInfo, ActConfig actConfig, long round, long oldP) {
        int configId = actConfig.getConfigId();
        long userId = userInfo.getId();
        UserCrossRankAct userRankAct = RankActManager.getUserCrossRankAct(userId, configId);
        if (userRankAct == null || userRankAct.getRound() != round) {
            return;
        }
        boolean isRedPoint = false;
        List<UserCrossRankActTask> userCrossRankActTaskList = RankActManager.getUserCrossRankActTaskList(userId, configId);
        Map<Integer, UserCrossRankActTask> userCrossRankActTaskMap = new HashMap<>();
        for (UserCrossRankActTask task : userCrossRankActTaskList) {
            if (task.getRound() == round) {
                userCrossRankActTaskMap.put(task.getTaskType(), task);
            }
        }
        CsGameSystem.RedPoint_RankactReward.Builder redPoint = CsGameSystem.RedPoint_RankactReward.newBuilder();
        int[] taskTypeArray = actConfig.getTimeTaskArray();
        JsonArray taskGetArray = userRankAct.getTaskGetArray();
        List<Integer> redPointList = new ArrayList<>();
        for (int taskGroup : taskTypeArray) {
            List<ActTask> taskList = ActDaysManager.getActTasksByGroupId(taskGroup);
            for (ActTask task : taskList) {
                UserCrossRankActTask userTask = userCrossRankActTaskMap.get(task.getTaskType());
                if (userTask == null) {
                    continue;
                }
                if (Tool.isInList(taskGetArray, task.getTaskType())) {
                    continue;
                }
                if (userTask.getCurP() >= task.getNum1()) {
                    redPointList.add(taskGroup);
                    isRedPoint = true;
                    break;
                }
            }
        }
        if (isRedPoint) {
            GameUser.sendRedPointPrompt(userInfo, null, SystemConstant.RED_POINT_RANKACT_RED_POINT, SystemConstant.RED_POINT_RANKACT_SUB_TYPE_TASK, configId, redPointList);
        }
    }

    public static <T extends BaseModel> void updateOuterTask(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, List<T> modelList, DayTaskInterface<T> function) {
        int serverId = userInfo.getServerId();
        ServerInfo server = ServerManager.getServerInfo(serverId);
        long curTime = TimeUtils.getCurTime();
        if (curTime >= TimeUtils.getStartTimeOfDay(server.getStartTime())) {
            int days = TimeUtils.getDiffDay(curTime, server.getStartTime())+1;//天数距离从第一天开始
            if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
                ConcurrentHashMap<Integer, ActConfig> configList = RankActManager.getActConfigList(ActConfig.GROUP_ID_LOCAL);
                if(configList != null) {
                    ActConfig actConfig = getActConfig(days, configList, false);
                    long[] times =actConfig.getConfigTime(ActConfig.GROUP_ID_LOCAL, server.getStartTime(), curTime);
                    if (times == null) {
                        return;
                    }
                    int actDays = getActDays(ActConfig.GROUP_ID_LOCAL);
                    long round = days / actDays; // 第几轮
                    if (days % actDays != 0) {
                        round += 1;
                    }
                    int curActDay = days % actDays;
                    if (curActDay == 0) {
                        curActDay = actDays;
                    }
                    List<ActTask> taskList = getTaskList(actConfig, taskType);
                    if (taskList.isEmpty()) {
                        return;
                    }

                    for (ActTask actTask : taskList) {
                        int param = actTask.getNum2();
                        int num = function.apply(modelList, param);
                        updateTask(pbUserData, userInfo, round, actConfig, taskType, curActDay, num, param, false);
                    }
                }
            }
        }
    }

    public static <T extends BaseModel> void updateCrossOuterTask(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, List<T> modelList, DayTaskInterface<T> function) {
        int serverId = userInfo.getServerId();
        ServerInfo server = ServerManager.getServerInfo(serverId);
        long curTime = TimeUtils.getCurTime();
        if (curTime >= TimeUtils.getStartTimeOfDay(server.getStartTime())) {
            int days = TimeUtils.getDiffDay(curTime, server.getStartTime())+1;
            if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
                return;
            }
            JsonObject actParam = isCrossRankAct(curTime);
            if (actParam == null) {
                return;
            }
            long round = actParam.getLong("round");
            int configId = actParam.getInteger("actid");
            int actDay = actParam.getInteger("actDay") + 1;
            if (!isJoinCrossRankAct(server, round)) {
                return;
            }
            ActConfig actConfig = RankActManager.getActConfig(configId);
            if (actConfig == null) {
                return;
            }
            List<ActTask> taskList = getTaskList(actConfig, taskType);
            if (taskList.isEmpty()) {
                return;
            }
            for (ActTask actTask : taskList) {
                int param = actTask.getNum2();
                int num = function.apply(modelList, param);
                updateCrossTask(pbUserData, userInfo, round, actConfig, actDay, taskType, num, param, false);
            }
        }
    }

    public static <T extends BaseModel> void updateOuterTaskProgress(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, List<T> modelList, DayTaskInterface<T> function) {
        updateOuterTask(pbUserData, userInfo, taskType, modelList, function);
        updateCrossOuterTask(pbUserData, userInfo, taskType, modelList, function);
    }

    public static List<ActTask> getTaskList(ActConfig actConfig, int taskType) {
        int[] timeTaskArray = actConfig.getTimeTaskArray();
        List<ActTask> taskList = new ArrayList<>();
        for (int groupId : timeTaskArray) {
            List<ActTask> list = ActDaysManager.getActTasksByGroupId(groupId, taskType);
            if (list == null || list.isEmpty()) {
                continue;
            }
            taskList.addAll(list);
        }
        return taskList;
    }

    public static List<ActTask> getTaskList(ActConfig actConfig, int taskType, int param) {
        int[] timeTaskArray = actConfig.getTimeTaskArray();
        List<ActTask> taskList = new ArrayList<>();
        for (int groupId : timeTaskArray) {
            List<ActTask> list = ActDaysManager.getActTaskByType(groupId, taskType, param);
            if (list.isEmpty()) {
                continue;
            }
            taskList.addAll(list);
        }
        return taskList;
   }

   public static List<ActRechargeTask> getRechargeTaskListByType(ActConfig actConfig, int taskType) {
        List<ActRechargeTask> taskList = new ArrayList<>();
        int[] rechargeTaskArray = actConfig.getRechargeTaskArray();
        for (int taskGroup : rechargeTaskArray) {
            List<ActRechargeTask> list = RankActManager.getActRechargeTaskListByType(taskGroup, taskType);
            if (null != list && !list.isEmpty()) {
                taskList.addAll(list);
            }
        }
        return taskList;
   }

    public static void reissueTaskReward(PBUserData.Builder pbUserData, UserInfo userInfo) {
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        long curTime = TimeUtils.getCurTime();
        if (curTime <= TimeUtils.getStartTimeOfDay(serverInfo.getStartTime())) {
            return;
        }

        ConcurrentHashMap<Integer, ActConfig> configList = getActConfigList(ActConfig.GROUP_ID_LOCAL);
        if (configList == null || configList.isEmpty()) {
            return;
        }
        for (ActConfig config : configList.values()) {
            long[] times = config.getConfigTime(serverInfo.getWarZone(), serverInfo.getStartTime(), curTime);
            if (times == null) {
                continue;
            }
            if (curTime <= times[1]) { // 活动未结束
                continue;
            }
            reissueTaskReward(pbUserData, userInfo, config);
        }
    }

    public static void reissueTaskReward(PBUserData.Builder pbUserData, UserInfo userInfo, ActConfig actConfig) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();

        UserRankAct userRankAct = RankActManager.getUserRankAct(userId, 1, configId);
        if (userRankAct == null) {
            userRankAct = new UserRankAct(userId, 1, configId);
            userRankAct.doCreate();
        }
        if (!userRankAct.needReissue()) {
            return;
        }
        reissueTaskReward(pbUserData, userInfo, actConfig, userRankAct);
        reissueRechargeTask(pbUserData, userInfo, actConfig, userRankAct);
        userRankAct.putReissueRound(userRankAct.getRound());
        userRankAct.update();
//        ProtoDataUtils.updatePBUserData(pbUserData, userRankAct);
    }

    private static void reissueTaskReward(PBUserData.Builder pbUserData, UserInfo userInfo, ActConfig actConfig, UserRankAct userRankAct) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        List<UserRankActTask> taskList = RankActManager.getRankActTaskList(userId, configId);
        if (taskList.isEmpty()) {
            return;
        }
        JsonArray taskGet = userRankAct.getTaskGetArray();
        ConcurrentHashMap<Integer, Long> rewardItemMap = new ConcurrentHashMap<>();
        boolean needUpdate = false;
        for (UserRankActTask task : taskList) {
            int taskId = task.getTaskType();
            int param = 0;
            if (taskId > 1000000) {
                taskId /= 1000000;
                param = taskId % 1000000;
            }
            List<ActTask> taskListConfig = getTaskList(actConfig, taskId, param);
            if (taskListConfig.isEmpty()) {
                continue;
            }
            for (ActTask actTask : taskListConfig) {
                if (Tool.isInList(taskGet, actTask.getId())) {
                    continue;
                }
                if (task.getCurP() >= actTask.getNum1()) {
                    RewardManager.mergeItemMap(rewardItemMap, actTask.getRewardItemList());
                    taskGet.add(actTask.getId());
                    needUpdate = true;
                }
            }
        }
        if (needUpdate) {
            List<RewardItem> rewardItemList = rewardItemMap.entrySet().stream().map(e -> new RewardItem(e.getKey(), e.getValue())).toList();
            userRankAct.putTaskGet(taskGet.toString());
            MailManager.sendSystemMail(userInfo.getId(), MailConstant.RANK_ACT_TASK_REWARD_TITLE,
                    MailConstant.RANK_ACT_TASK_REWARD_CONTENT, rewardItemList, LogType.RANK_ACT_TASK_REISSUE_REWARD);
        }
    }

    public static void reissueCrossTask(PBUserData.Builder pbUserData, UserInfo userInfo) {
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        long curTime = TimeUtils.getCurTime();
        if (curTime <= TimeUtils.getStartTimeOfDay(serverInfo.getStartTime())) {
            return;
        }
        long actStartTime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
        if (curTime <= actStartTime) {
            return;
        }
        JsonObject actInfo = isCrossRankAct(curTime);
        if (actInfo == null) {
            return;
        }

        long round = actInfo.getLong("round");
        if (!isJoinCrossRankAct(serverInfo, round)) {
            return;
        }

        ConcurrentHashMap<Integer, ActConfig> configList = getActConfigList(ActConfig.GROUP_ID_GLOBAL);
        if (configList == null || configList.isEmpty()) {
            return;
        }
        for (ActConfig config : configList.values()) {
            reissueCrossTaskReward(pbUserData, userInfo, config, round, curTime);
        }
    }

    public static void reissueCrossTaskReward(PBUserData.Builder pbUserData, UserInfo userInfo, ActConfig actConfig, long round, long curTime) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        long actStartTime = TimeUtils.getTimeStrIntValue(AllParam.getCrossRankActStartTime());
        long[] times = actConfig.getConfigTime(0, actStartTime, curTime);
        if (times == null) {
            return;
        }

        UserCrossRankAct userRankAct = RankActManager.getUserCrossRankAct(userId, configId);
        if (userRankAct == null) {
            userRankAct = new UserCrossRankAct(userId, configId, round);
            userRankAct.doCreate();
        }
        if (curTime <= times[1] && userRankAct.getRound() == round) { // 活动未结束
            return;
        }
        if (!userRankAct.needReissue()) {
            return;
        }
        reissueCrossTaskReward(userInfo, actConfig, userRankAct);
        reissueCrossRechargeTask(userInfo, actConfig, userRankAct);
        userRankAct.putReissueRound(userRankAct.getRound());
        userRankAct.update();
//        ProtoDataUtils.updatePBUserData(pbUserData, userRankAct);
    }

    public static void reissueCrossTaskReward(UserInfo userInfo, ActConfig actConfig, UserCrossRankAct userRankAct) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        List<UserCrossRankActTask> taskList = RankActManager.getUserCrossRankActTaskList(userId, configId);
        if (taskList.isEmpty()) {
            return;
        }
        JsonArray taskGet = userRankAct.getTaskGetArray();
        ConcurrentHashMap<Integer, Long> rewardItemMap = new ConcurrentHashMap<>();
        boolean needUpdate = false;
        long curRound = userRankAct.getRound();
        for (UserCrossRankActTask task : taskList) {
            if (task.getRound() != curRound) {
                continue;
            }
            int taskId = task.getTaskType();
            int param = 0;
            if (taskId > 1000000) {
                taskId /= 1000000;
                param = taskId % 1000000;
            }
            List<ActTask> taskListConfig = getTaskList(actConfig, taskId, param);
            if (taskListConfig.isEmpty()) {
                continue;
            }
            for (ActTask actTask : taskListConfig) {
                if (Tool.isInList(taskGet, actTask.getId())) {
                    continue;
                }
                if (task.getCurP() >= actTask.getNum1()) {
                    RewardManager.mergeItemMap(rewardItemMap, actTask.getRewardItemList());
                    taskGet.add(actTask.getId());
                    needUpdate = true;
                }
            }
        }
        if (needUpdate) {
            List<RewardItem> rewardItemList = rewardItemMap.entrySet().stream().map(e -> new RewardItem(e.getKey(), e.getValue())).toList();
            userRankAct.putTaskGet(taskGet.toString());
            MailManager.sendSystemMail(userInfo.getId(), MailConstant.RANK_ACT_CROSS_TASK_TITLE,
                    MailConstant.RANK_ACT_CROSS_TASK_CONTENT, rewardItemList, LogType.RANK_ACT_CROSS_TASK_REISSUE_REWARD);
        }
    }

    public static void reissueTask(PBUserData.Builder pbUserData, UserInfo userInfo) {
        reissueTaskReward(pbUserData, userInfo);
        reissueCrossTask(pbUserData, userInfo);
    }

    /**
     * 判断是否有公会排名
     */
    public static boolean hasUnionRank(UserInfo userInfo) {
        AtomicLong roundId = new AtomicLong();
        ActConfig actConfig = RankActManager.getActConfig(userInfo, roundId);

        if (actConfig == null) {
            return false;
        }
        List<ActTopRanking> rankingList = RankActManager.getActTopRankingList(actConfig.getRankList());
        return rankingList.stream().anyMatch(ranking -> ranking.getType() == ActTopRanking.RANK_TYPE_UNION_EXP);
    }

    public static void updateRechargeTask(PBUserData.Builder pbUserData, UserInfo userInfo, long vipScore) {
        updateChargeTaskProgress(pbUserData, userInfo, vipScore);
        updateCrossRechargeTaskProgress(pbUserData, userInfo, vipScore);
    }

    public static void updateChargeTaskProgress(PBUserData.Builder pbUserData, UserInfo userInfo, long vipScore) {
        updateChargeTaskProgress(pbUserData, userInfo, ActRechargeTask.TASK_TYPE_VIP_SCORE_DAILY, vipScore);
        updateChargeTaskProgress(pbUserData, userInfo, ActRechargeTask.TASK_TYPE_VIP_SCORE, vipScore);
        updateChargeTaskProgress(pbUserData, userInfo, ActRechargeTask.TASK_TYPE_DAY_CHARGE, 1);
    }
    public static void updateChargeTaskProgress(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, long num) {
        int serverId = userInfo.getServerId();
        ServerInfo server = ServerManager.getServerInfo(serverId);
        long curTime = TimeUtils.getCurTime();
        if (curTime >= TimeUtils.getStartTimeOfDay(server.getStartTime())) {
            int days = TimeUtils.getDiffDay(curTime, server.getStartTime())+1;//天数距离从第一天开始
            if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
                ConcurrentHashMap<Integer, ActConfig> configList = RankActManager.getActConfigList(ActConfig.GROUP_ID_LOCAL);
                if(configList != null) {
                    ActConfig actConfig = getActConfig(days, configList, false);
                    long oldP = 0;
                    if(actConfig != null) {
                        UserRechargeActTask userRechargeActTask = RankActManager.getUserRechargeActTask(userInfo.getId(), actConfig.getConfigId(), taskType);
                        if(userRechargeActTask == null) {
                            userRechargeActTask = new UserRechargeActTask(userInfo.getId(), 1, actConfig.getConfigId(), taskType, num);
                            userRechargeActTask.doCreate();
                        } else {
                            oldP = userRechargeActTask.getCurP();
                            if (taskType == ActRechargeTask.TASK_TYPE_DAY_CHARGE) {
                                if (!TimeUtils.isToday(userRechargeActTask.getRechargeTime())) {
                                    userRechargeActTask.putRechargeTime(TimeUtils.getCurTime());
                                    userRechargeActTask.addTaskValue(num);
                                }
                            } else {
                                userRechargeActTask.addTaskValue(num);
                            }
                            userRechargeActTask.update();
                        }
                        ProtoDataUtils.updatePBUserData(pbUserData, userRechargeActTask);
                        checkLocalRechargeRedPoint(userInfo, actConfig, userRechargeActTask, oldP);
                    }
                }
            }
        }
    }

    public static void updateCrossRechargeTaskProgress(PBUserData.Builder pbUserData, UserInfo userInfo, long vipScore) {
        updateCrossRechargeTaskProgress(pbUserData, userInfo, ActRechargeTask.TASK_TYPE_VIP_SCORE_DAILY, vipScore);
        updateCrossRechargeTaskProgress(pbUserData, userInfo, ActRechargeTask.TASK_TYPE_VIP_SCORE, vipScore);
        updateCrossRechargeTaskProgress(pbUserData, userInfo, ActRechargeTask.TASK_TYPE_DAY_CHARGE, 1);
    }
    public static void updateCrossRechargeTaskProgress(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, long num) {
        int serverId = userInfo.getServerId();
        ServerInfo server = ServerManager.getServerInfo(serverId);
        long curTime = TimeUtils.getCurTime();
        if (curTime >= TimeUtils.getStartTimeOfDay(server.getStartTime())) {
            int days = TimeUtils.getDiffDay(curTime, server.getStartTime())+1;//天数距离从第一天开始
            if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
                return;
            }

            JsonObject actInfo = isCrossRankAct(curTime);
            if(actInfo == null) {
                return;
            }
            long round = actInfo.getLong("round");
            int configId = actInfo.getInteger("actid");
            ActConfig actConfig = getActConfig(configId);
            if(actConfig != null) {
                if (!isJoinCrossRankAct(server, round)) {
                    return;
                }
                long oldP = 0;
                UserCrossRechargeActTask userRechargeActTask = RankActManager.getUserCrossRechargeActTask(userInfo.getId(), actConfig.getConfigId(), taskType);
                if(userRechargeActTask == null) {
                    userRechargeActTask = new UserCrossRechargeActTask(userInfo.getId(), round, actConfig.getConfigId(), taskType, num);
                    userRechargeActTask.doCreate();
                } else {
                    userRechargeActTask.checkRound(round);
                    oldP = userRechargeActTask.getCurP();
                    if (taskType == ActRechargeTask.TASK_TYPE_DAY_CHARGE) {
                        if (!TimeUtils.isToday(userRechargeActTask.getRechargeTime())) {
                            userRechargeActTask.putRechargeTime(TimeUtils.getCurTime());
                            userRechargeActTask.addTaskValue(num);
                        }
                    } else {
                        userRechargeActTask.addTaskValue(num);
                    }
                    userRechargeActTask.update();
                }
                ProtoDataUtils.updatePBUserData(pbUserData, userRechargeActTask);
                checkCrossRankRechargeTaskRedPoint(userInfo, actConfig, userRechargeActTask, round, oldP);
            }
        }
    }

    public static void reissueRechargeTask(PBUserData.Builder pbUserData, UserInfo userInfo, ActConfig actConfig, UserRankAct userRankAct) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        List<UserRechargeActTask> taskList = RankActManager.getUserRechargeActTaskList(userId, configId);
        if (taskList.isEmpty()) {
            return;
        }
        JsonArray taskGet = userRankAct.getRechargeTaskGetArray();
        ConcurrentHashMap<Integer, Long> rewardItemMap = new ConcurrentHashMap<>();
        boolean needUpdate = false;
        for (UserRechargeActTask task : taskList) {
            List<ActRechargeTask> taskListConfig = getRechargeTaskListByType(actConfig, task.getTaskType());
            if (taskListConfig.isEmpty()) {
                continue;
            }
            for (ActRechargeTask actTask : taskListConfig) {
                if (Tool.isInList(taskGet, actTask.getId())) {
                    continue;
                }
                if (task.getCurP() >= actTask.getNum()) {
                    RewardManager.mergeItemMap(rewardItemMap, CommonUtils.takeReawrdItemFromStr(actTask.getReward()));
                    taskGet.add(actTask.getId());
                    needUpdate = true;
                }
            }
        }
        if (needUpdate) {
            List<RewardItem> rewardItemList = rewardItemMap.entrySet().stream().map(e -> new RewardItem(e.getKey(), e.getValue())).toList();
            userRankAct.putRechargeTaskGet(taskGet.toString());
            userRankAct.update();
            MailManager.sendSystemMail(userInfo.getId(), MailConstant.RANK_ACT_RECHARGE_REWARD_TITLE,
                    MailConstant.RANK_ACT_RECHARGE_REWARD_CONTENT, rewardItemList, LogType.RANK_ACT_TASK_REISSUE_REWARD);
        }
    }

    public static void reissueCrossRechargeTask(UserInfo userInfo, ActConfig actConfig, UserCrossRankAct userCrossRankAct) {
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        List<UserCrossRechargeActTask> taskList = RankActManager.getUserCrossRechargeActTaskList(userId, configId);
        if (taskList.isEmpty()) {
            return;
        }
        JsonArray taskGet = userCrossRankAct.getRechargeTaskGetArray();
        ConcurrentHashMap<Integer, Long> rewardItemMap = new ConcurrentHashMap<>();
        boolean needUpdate = false;
        for (UserCrossRechargeActTask task : taskList) {
            List<ActRechargeTask> taskListConfig = getRechargeTaskListByType(actConfig, task.getTaskType());
            if (taskListConfig.isEmpty()) {
                continue;
            }
            for (ActRechargeTask actTask : taskListConfig) {
                if (Tool.isInList(taskGet, actTask.getId())) {
                    continue;
                }
                if (task.getCurP() >= actTask.getNum()) {
                    RewardManager.mergeItemMap(rewardItemMap, CommonUtils.takeReawrdItemFromStr(actTask.getReward()));
                    taskGet.add(actTask.getId());
                    needUpdate = true;
                }
            }
        }
        if (needUpdate) {
            List<RewardItem> rewardItemList = rewardItemMap.entrySet().stream().map(e -> new RewardItem(e.getKey(), e.getValue())).toList();
            userCrossRankAct.putRechargeTaskGet(taskGet.toString());
            userCrossRankAct.update();
            MailManager.sendSystemMail(userInfo.getId(), MailConstant.RANK_ACT_CROSS_RECHARGE_REWARD_TITLE,
                    MailConstant.RANK_ACT_CROSS_RECHARGE_REWARD_CONTENT, rewardItemList, LogType.RANK_ACT_TASK_REISSUE_REWARD);
        }
    }

    public static void updateRechargeGift(PBUserData.Builder pbUserData, UserInfo userInfo, IapGift iapGift) {

    }

    public static ActRecharge getActRechargeList(UserInfo userInfo, IapGift iapGift) {
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        long curTime = TimeUtils.getCurTime();
        if (curTime <= TimeUtils.getStartTimeOfDay(serverInfo.getStartTime())) {
            return null;
        }
        ConcurrentHashMap<Integer, ActConfig> actConfigMap = getActConfigList(ActConfig.GROUP_ID_LOCAL);
        if (actConfigMap == null || actConfigMap.isEmpty()) {
            return null;
        }
        int days = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        if (days > getActDays(ActConfig.GROUP_ID_LOCAL)) {
            return null;
        }
        ActConfig curConfig = getActConfig(days, actConfigMap, false);
        if (curConfig == null) {
            return null;
        }

        return getActRechargeByGift(curConfig, iapGift);
    }

    public static ActRecharge getCrossActRechargeList(UserInfo userInfo, IapGift iapGift) {
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        long curTime = TimeUtils.getCurTime();
        if (curTime <= TimeUtils.getStartTimeOfDay(serverInfo.getStartTime())) {
            return null;
        }
        JsonObject actInfo = isCrossRankAct(curTime);
        if (actInfo == null) {
            return null;
        }
        int configId = actInfo.getInteger("actid");
        ActConfig curConfig = getActConfig(configId);
        if (curConfig == null) {
            return null;
        }

        return getActRechargeByGift(curConfig, iapGift);
    }


    public static boolean isJoinCrossRankAct(ServerInfo serverInfo, long round) {
        RankActGroup rankActGroup = RankActManager.getRankActGroup(serverInfo.getWarZone(), round);
        if (rankActGroup == null) {
            return false;
        }
        JsonArray serverList = rankActGroup.getServerListArray();
        return Tool.isInList(serverList, serverInfo.getServerId());
    }

    public static ActRecharge getSpecialActRecharge(ActConfig actConfig, int iapId) {
        int[] rechargeArray = actConfig.getRechargeArray();
        for (int recharge : rechargeArray) {
            ActRecharge actRecharge = getActRechargeByType(recharge, ActRecharge.TYPE_DAILY_SPECIAL_OFFER);
            if (actRecharge != null) {
                int[] paramArray = actRecharge.getParamterArray();
                if (paramArray != null && Tool.isInList(paramArray, iapId)) {
                    return actRecharge;
                }
            }
        }
        return null;
    }

    public static ActRecharge getActRechargeByGift(ActConfig actConfig, IapGift iapGift) {
        int rechargeType = 0;
        switch (iapGift.getType()) { // 把礼包类型转化为相应的模板类型
            case IapGift.TYPE_RECHARGE_ACT_DAILY_SPECIAL_OFFER:
                rechargeType = ActRecharge.TYPE_DAILY_SPECIAL_OFFER;
                break;
            case IapGift.TYPE_RECHARGE_ACT_NORMAL:
                rechargeType = ActRecharge.TYPE_NORMAL;
                break;
            case IapGift.TYPE_RECHARGE_ACT_RANKACT:
                rechargeType= ActRecharge.TYPE_RANK_ACT;
                break;
            default:
                return null;
        }
        return getActRechargeByType(actConfig, iapGift.getId(), rechargeType);
    }

    public static ActRecharge getActRechargeByType(ActConfig actConfig, int iapGiftId, int type) {
        int[] rechargeArray = actConfig.getRechargeArray();
        for (int recharge : rechargeArray) {
            ActRecharge actRecharge = getActRechargeByType(recharge, type);
            if (actRecharge != null) {
                int[] paramArray = actRecharge.getParamterArray();
                if (paramArray != null && Tool.isInList(paramArray, iapGiftId)) {
                    return actRecharge;
                }
            }
        }
        return null;
    }

    public static boolean isLocalRankAct(UserInfo userInfo) {
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        int localDays = RankActManager.getActDays(ActConfig.GROUP_ID_LOCAL);
        long curTime = TimeUtils.getCurTime();
        int serverOpenDays = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        if (serverOpenDays <= localDays) {
            return true;
        }
        return false;
    }
    public static boolean isCrossRankAct(UserInfo userInfo) {
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        int localDays = RankActManager.getActDays(ActConfig.GROUP_ID_LOCAL);
        long curTime = TimeUtils.getCurTime();
        int serverOpenDays = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        if (serverOpenDays <= localDays) {
            return false;
        }
        JsonObject rankActInfo = isCrossRankAct(curTime);
        if (rankActInfo == null) {
            return false;
        }
        long round = rankActInfo.getLong("round");
        return isJoinCrossRankAct(serverInfo, round);
    }

    public static ErrorWord checkActRechargeBuy(UserInfo userInfo, IapGift iapGift) {
        long curTime = TimeUtils.getCurTime();
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        ActConfig curConfig = getLocalRankAct(serverInfo, curTime);
        if (curConfig == null) {
            return ErrorWord.WRONG_STATUS;
        }
//        int iapId = iapGift.getId();
        ActRecharge actRecharge = getActRechargeList(userInfo, iapGift);
        if (actRecharge == null) {
            return ErrorWord.NOT_DATA;
        }
        UserRankAct userRankAct = getUserRankAct(userInfo.getId(), 1, curConfig.getConfigId());
        if (userRankAct == null) {
            userRankAct = new UserRankAct(userInfo.getId(), 1, curConfig.getConfigId());
            userRankAct.doCreate();
        }
        if (!checkBuyCount(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), iapGift)) {
            return ErrorWord.ALREADY_MAX;
        }
        if (actRecharge.getType() == ActRecharge.TYPE_DAILY_SPECIAL_OFFER) {
            if (invalidRechargeBuy(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), actRecharge, iapGift)) {
                return ErrorWord.INVALID_OPERATION;
            }
        }

        return ErrorWord.SUCCESS;
    }

    /**
     * 是否出现一键礼包购买冲突
     */
    public static boolean invalidRechargeBuy(JsonObject dayBuyInfo, JsonObject buyInfo, ActRecharge actRecharge, IapGift iapGift) {
        boolean isCurOneKey = false;
        JsonObject param = iapGift.getParams();
        isCurOneKey = param.getInteger("one_key", 0) == 1; // 当前礼包是否一键礼包
        JsonObject rechargeBuyInfo;
        if (iapGift.getLimitType() == IapGift.LIMIT_TYPE_DAY) {
            rechargeBuyInfo =dayBuyInfo;
        } else {
            rechargeBuyInfo = buyInfo;
        }
        int[] rechargeArray = actRecharge.getParamterArray();
        for (int giftId : rechargeArray) {
            if (giftId == iapGift.getId()) {
                continue;
            }
            IapGift iapGift1 = IapManager.getIapGift(giftId);
            if (iapGift1 != null) {
                String iapKey = String.valueOf(giftId);
                if (rechargeBuyInfo.containsKey(iapKey)) {
                    if (isCurOneKey) {
                        return true; // 当前礼包是一键礼包
                    } else {
                        JsonObject param1 = iapGift1.getParams();
                        if (param1.getInteger("one_key", 0) == 1) {
                            return true; // 已购买过一键礼包
                        }
                    }
                }
            }
        }
        return false;
    }


    public static ErrorWord checkCrossActRechargeBuy(UserInfo userInfo, IapGift iapGift) {
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        long curTime = TimeUtils.getCurTime();
        if (curTime <= TimeUtils.getStartTimeOfDay(serverInfo.getStartTime())) {
            return ErrorWord.WRONG_STATUS;
        }
        int days = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
            return ErrorWord.WRONG_STATUS;
        }
        JsonObject actInfo = isCrossRankAct(curTime);
        if (actInfo == null) {
            return ErrorWord.WRONG_STATUS;
        }
        long round = actInfo.getLong("round");
        if (!isJoinCrossRankAct(serverInfo, round)) {
            return ErrorWord.WRONG_STATUS;
        }
        int configId = actInfo.getInteger("actid");
        ActConfig actConfig = getActConfig(configId);
        if (actConfig == null) {
            return ErrorWord.NOT_DATA;
        }
        ActRecharge actRecharge = getActRechargeByGift(actConfig, iapGift);
        if (actRecharge == null) {
            return ErrorWord.NOT_DATA;
        }

        UserCrossRankAct userRankAct = getUserCrossRankAct(userInfo.getId(), actConfig.getConfigId());
        if (userRankAct == null) {
            userRankAct = new UserCrossRankAct(userInfo.getId(), actConfig.getConfigId(), round);
            userRankAct.doCreate();
        }
        userRankAct.checkReset(round);
        if (!(checkBuyCount(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), iapGift))) {
            return ErrorWord.ALREADY_MAX;
        }
        if (actRecharge.getType() == ActRecharge.TYPE_DAILY_SPECIAL_OFFER) {
            if (invalidRechargeBuy(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), actRecharge, iapGift)) {
                return ErrorWord.INVALID_OPERATION;
            }
        }
        return null;
    }

    public static ActConfig getLocalRankAct(ServerInfo serverInfo, long curTime) {
        if (curTime <= TimeUtils.getStartTimeOfDay(serverInfo.getStartTime())) {
            return null;
        }
        int days = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        if (days > getActDays(ActConfig.GROUP_ID_LOCAL)) {
            return null;
        }

        ConcurrentHashMap<Integer, ActConfig> actConfigMap = getActConfigList(ActConfig.GROUP_ID_LOCAL);
        if (actConfigMap == null || actConfigMap.isEmpty()) {
            return null;
        }
        return getActConfig(days, actConfigMap, false);
    }

    public static void updateRechargeBuy(PBUserData.Builder pbuserData, UserInfo userInfo, IapGift iapGift) {
        long userId = userInfo.getId();
        int iapId = iapGift.getId();
        long curTime = TimeUtils.getCurTime();
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        ActConfig curConfig = getLocalRankAct(serverInfo, curTime);
        if (curConfig == null) {
            return;
        }
        ActRecharge actRecharge = getActRechargeList(userInfo, iapGift);
        if (actRecharge == null) {
            return;
        }
        UserRankAct userRankAct = getUserRankAct(userId, 1, curConfig.getConfigId());
        if (userRankAct == null) {
            userRankAct = new UserRankAct(userId, 1, curConfig.getConfigId());
            userRankAct.doCreate();
        }
        if (!checkBuyCount(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), iapGift)) {
            return;
        }
        if (invalidRechargeBuy(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), actRecharge, iapGift)) {
            return;
        }
        saveBuyCount(userRankAct, iapGift);
        userRankAct.update();
        ProtoDataUtils.updatePBUserData(pbuserData, userRankAct);
    }

    public static boolean checkBuyCount(JsonObject dayBuyInfo, JsonObject buyInfo, IapGift iapGift) {
        String iapKey = String.valueOf(iapGift.getId());
        if (iapGift.getLimitType() == IapGift.LIMIT_TYPE_DAY) {
            int buyCount = dayBuyInfo.getInteger(iapKey, 0);
            return buyCount < iapGift.getLimitNum();
        } else {
            int buyCount = buyInfo.getInteger(iapKey, 0);
            return buyCount < iapGift.getLimitNum();
        }
    }

    public static void saveBuyCount(UserRankAct userRankAct, IapGift iapGift) {
        String iapKey = String.valueOf(iapGift.getId());
        if (iapGift.getLimitType() == IapGift.LIMIT_TYPE_DAY) {
            JsonObject dayBuyInfo = userRankAct.getRechargeDayBuyJson();
            int buyCount = dayBuyInfo.getInteger(iapKey, 0);
            dayBuyInfo.put(iapKey, buyCount + 1);
            userRankAct.putRechargeDayBuy(dayBuyInfo.toString());
        } else {
            JsonObject buyInfo = userRankAct.getRechargeBuyJson();
            int buyCount = buyInfo.getInteger(iapKey, 0);
            buyInfo.put(iapKey, buyCount + 1);
            userRankAct.putRechargeBuy(buyInfo.toString());
        }
    }

    public static void updateCrossRechargeBuy(PBUserData.Builder pbuserData, UserInfo userInfo, IapGift iapGift) {
        long userId = userInfo.getId();
        int iapId = iapGift.getId();
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        long curTime = TimeUtils.getCurTime();
        if (curTime <= TimeUtils.getStartTimeOfDay(serverInfo.getStartTime())) {
            return;
        }
        int days = TimeUtils.getDiffDay(serverInfo.getStartTime(), curTime) + 1;
        if (days <= getActDays(ActConfig.GROUP_ID_LOCAL)) {
            return;
        }
        JsonObject actInfo = isCrossRankAct(curTime);
        if (actInfo == null) {
            return;
        }
        long round = actInfo.getLong("round");
        if (!isJoinCrossRankAct(serverInfo, round)) {
            return;
        }
        int configId = actInfo.getInteger("actid");
        ActConfig actConfig = getActConfig(configId);
        if (actConfig == null) {
            return;
        }

        ActRecharge actRecharge = getCrossActRechargeList(userInfo, iapGift);
        if (actRecharge == null) {
            return;
        }
        UserCrossRankAct userRankAct = getUserCrossRankAct(userId, actConfig.getConfigId());
        if (userRankAct == null) {
            userRankAct = new UserCrossRankAct(userId, actConfig.getConfigId(), round);
            userRankAct.doCreate();
        }
        if (!checkBuyCount(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), iapGift)) {
            return;
        }
        if (iapGift.getType() == IapGift.TYPE_RECHARGE_ACT_DAILY_SPECIAL_OFFER) {
            if (invalidRechargeBuy(userRankAct.getRechargeDayBuyJson(), userRankAct.getRechargeBuyJson(), actRecharge, iapGift)) {
                return;
            }
        }
        saveCrossBuyCount(userRankAct, iapGift);
        userRankAct.update();
        ProtoDataUtils.updatePBUserData(pbuserData, userRankAct);
    }

    public static void saveCrossBuyCount(UserCrossRankAct userRankAct, IapGift iapGift) {
        String iapKey = String.valueOf(iapGift.getId());
        if (iapGift.getLimitType() == IapGift.LIMIT_TYPE_DAY) {
            JsonObject dayBuyInfo = userRankAct.getRechargeDayBuyJson();
            int buyCount = dayBuyInfo.getInteger(iapKey, 0);
            dayBuyInfo.put(iapKey, buyCount + 1);
            userRankAct.putRechargeDayBuy(dayBuyInfo.toString());
        } else {
            JsonObject buyInfo = userRankAct.getRechargeBuyJson();
            int buyCount = buyInfo.getInteger(iapKey, 0);
            buyInfo.put(iapKey, buyCount + 1);
            userRankAct.putRechargeBuy(buyInfo.toString());
        }
    }


    /**
     * 测试服跨服匹配分组
     */
    public static void testMatchCrossRankAct() {
        logger.info("#====== testMatchCrossRankAct start ======");

        try {
            long curDay = TimeUtils.getStartTimeOfDay(TimeUtils.getCurTime());
//            System.out.println("tomorrow: " + nextDay);
            JsonObject nextActInfo = isCrossRankAct(curDay);

            if (nextActInfo != null) {
                Map<Integer, ServerInfo> serverInfoMap = ServerManager.getServerList();
                List<Integer> groupList = new ArrayList<>();
                for (ServerInfo serverInfo : serverInfoMap.values()) {
                    if (serverInfo.getWarZone() == 0) {
                        continue;
                    }
                    if (groupList.contains(serverInfo.getWarZone())) {
                        continue;
                    }
                    groupList.add(serverInfo.getWarZone());
                }
                for (Integer groupId : groupList) {
                    JsonObject param = new JsonObject(nextActInfo.toString());
                    param.put("groupId", groupId);
                    matchCrossRankAct(param);
//                    TimedTaskManager.sendWorkTask(TimeTaskCmd.WORK_CROSS_RANK_ACT_MATCH, param);
                }
            }
        } catch (Exception e) {
            logger.error("testMatchCrossRankAct error", e);
        }
    }

    public static boolean checkRedPoint(UserInfo userInfo, CsGameSystem.CSGameSystemRedPointResponse.Builder builder) {
        if (isLocalRankAct(userInfo)) {
            return checkRankRedPoint(userInfo, builder);
        } else if (isCrossRankAct(userInfo)){
            return checkCrossRankRedPoint(userInfo, builder);
        }
        return false;
    }

    public static boolean checkLocalRechargeRedPoint(UserInfo userInfo, ActConfig actConfig, UserRechargeActTask userRechargeAct, long oldP) {
        boolean isRedPoint = false;
        UserRankAct userRankAct = getUserRankAct(userInfo.getId(), 1, actConfig.getConfigId());
        if (userRankAct == null) {
            return false;
        }

//        List<UserRechargeActTask> userRechargeActTaskList = getUserRechargeActTaskList(userInfo.getId(), actConfig.getConfigId());
//        ConcurrentHashMap<Integer, UserRechargeActTask> userTaskMap = new ConcurrentHashMap<>();
//        for (UserRechargeActTask task : userRechargeActTaskList) {
//            userTaskMap.put(task.getTaskType(), task);
//        }
        int[] rechargeTaskList = actConfig.getRechargeTaskArray();
        JsonArray rechargeTaskGet = userRankAct.getRechargeTaskGetArray();
        List<Integer> rdArray = new ArrayList<>();
        for (int taskGroup : rechargeTaskList) {
            List<ActRechargeTask> actRechargeTasks = new ArrayList<>(getActRechargeTaskList(taskGroup).values());
            for (ActRechargeTask actRechargeTask : actRechargeTasks) {
//                UserRechargeActTask userTask = userTaskMap.getOrDefault(actRechargeTask.getTaskType(), null);
                if (userRechargeAct.getTaskType() != actRechargeTask.getTaskType()) {
                    break;
                }
                if (Tool.isInList(rechargeTaskGet, actRechargeTask.getId())) {
                    continue;
                }
                if (oldP < actRechargeTask.getNum() && userRechargeAct.getCurP() >= actRechargeTask.getNum()) {
                    if (!Tool.isInList(rdArray, actRechargeTask.getTaskType())) {
                        rdArray.add(actRechargeTask.getTaskType());
                    }
                    isRedPoint = true;
                    break;
                }
            }
        }
        if (isRedPoint) {
            GameUser.sendRedPointPrompt(userInfo, null, SystemConstant.RED_POINT_RANKACT_RED_POINT, SystemConstant.RED_POINT_RANKACT_SUB_TYPE_RECHARGE, actConfig.getConfigId(), rdArray);
        }
        return isRedPoint;
    }

    public static boolean checkRankRedPoint(UserInfo userInfo, CsGameSystem.CSGameSystemRedPointResponse.Builder builder) {
        boolean isRedPoint = false;
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        int day = TimeUtils.getDiffDay(serverInfo.getStartTime(), TimeUtils.getCurTime()) + 1;
        int allDay = RankActManager.getActDays(ActConfig.GROUP_ID_LOCAL);
        if (day > allDay) {
            return false;
        }
        ConcurrentHashMap<Integer, ActConfig> configList = RankActManager.getActConfigList(ActConfig.GROUP_ID_LOCAL);
        if (configList == null || configList.isEmpty()) {
            return false;
        }
        ActConfig actConfig = RankActManager.getActConfig(day, configList, false);
        if (actConfig == null) {
            return false;
        }
        UserRankAct userRankAct = getUserRankAct(userInfo.getId(), 1, actConfig.getConfigId());
        if (userRankAct == null) {
            return false;
        }
        // 限时任务
        List<UserRankActTask> userTaskList = getUserRankActTaskList(userInfo.getId(), 1, actConfig.getConfigId());
        ConcurrentHashMap<Integer, UserRankActTask> taskMap = new ConcurrentHashMap<>();
        for (UserRankActTask task : userTaskList) {
            taskMap.put(task.getTaskType(), task);
        }
        CsGameSystem.RedPoint_RankactReward.Builder redPoint = CsGameSystem.RedPoint_RankactReward.newBuilder();
        int[] taskList = actConfig.getTimeTaskArray();
        JsonArray taskGet = userRankAct.getTaskGetArray();
        for (int taskGroup : taskList) {
            List<ActTask> actTasks = ActDaysManager.getActTasksByGroupId(taskGroup);
            for (ActTask task : actTasks) {
                UserRankActTask userTask = taskMap.getOrDefault(task.getTaskType(), null);
                if (userTask == null) {
                    continue;
                }
                if (taskGet.contains(userTask.getId())) {
                    continue;
                }
                if (userTask.getCurP() >= task.getNum1()) {
                    redPoint.setConfigId(actConfig.getConfigId());
                    redPoint.addTaskGroups(taskGroup);
                    isRedPoint = true;
                    break;
                }
            }
        }
        List<UserRechargeActTask> userRechargeActTaskList = getUserRechargeActTaskList(userInfo.getId(), actConfig.getConfigId());
        ConcurrentHashMap<Integer, UserRechargeActTask> userTaskMap = new ConcurrentHashMap<>();
        for (UserRechargeActTask task : userRechargeActTaskList) {
            userTaskMap.put(task.getTaskType(), task);
        }
        int[] rechargeTaskList = actConfig.getRechargeTaskArray();
        JsonArray rechargeTaskGet = userRankAct.getRechargeTaskGetArray();
        for (int taskGroup : rechargeTaskList) {
            List<ActRechargeTask> actRechargeTasks = new ArrayList<>(getActRechargeTaskList(taskGroup).values());
            for (ActRechargeTask actRechargeTask : actRechargeTasks) {
                UserRechargeActTask userTask = userTaskMap.getOrDefault(actRechargeTask.getTaskType(), null);
                if (userTask == null) {
                    continue;
                }
                if (Tool.isInList(rechargeTaskGet, actRechargeTask.getId())) {
                    continue;
                }
                if (userTask.getCurP() >= actRechargeTask.getNum()) {
                    redPoint.setConfigId(actConfig.getConfigId());
                    redPoint.addRechargeTasks(actRechargeTask.getTaskType());
                    isRedPoint = true;
                    break;
                }
            }
        }
        if (actConfig.isInGetRewardTime(1, serverInfo.getStartTime(), TimeUtils.getCurTime())) {
            JsonArray rankGet = userRankAct.getRankGetArray();
            int rankList = actConfig.getRankList();
            List<ActTopRanking> rankingList = RankActManager.getActTopRankingList(rankList);
            for (ActTopRanking ranking : rankingList) {
                if (!Tool.isInList(rankGet, ranking.getType())) {
                    redPoint.setConfigId(actConfig.getConfigId());
                    redPoint.setIsReward(true);
                    isRedPoint = true;
                    break;
                }
            }
        }
        int[] shopIdArray = actConfig.getShopIdArray();
        List<UserRankActShop> userShopList = getUserRankActShopList(userInfo.getId(), actConfig.getConfigId());
        Map<Integer, UserRankActShop> userShopMap = userShopList.stream().collect(Collectors.toMap(UserRankActShop::getShopId, v -> v));
        for (int i = 0; i < shopIdArray.length; i++) {
            int shopId = shopIdArray[i];
            Shop shop = ShopManager.getShop(shopId);
            if (shop == null) {
                continue;
            }
            if (shop.getIsFree() == 1) {
                UserRankActShop userShop = userShopMap.getOrDefault(shopId, null);
                if (userShop == null || userShop.getNum() < shop.getLimitNum()) {
                    redPoint.setConfigId(actConfig.getConfigId());
                    redPoint.setIsFreeShop(true);
                    isRedPoint = true;
                    break;
                }
            }
        }
        if (isRedPoint) {
            builder.setRankactReward(redPoint);
        }
        return isRedPoint;
    }

    public static boolean checkCrossRankRechargeTaskRedPoint(UserInfo userInfo, ActConfig actConfig, UserCrossRechargeActTask userRechargeActTask, long round, long oldP) {
        boolean isRedPoint = false;
        long userId = userInfo.getId();
        int configId = actConfig.getConfigId();
        UserCrossRankAct userRankAct = RankActManager.getUserCrossRankAct(userId, configId);
        if (userRankAct == null || userRankAct.getRound() != round) {
            return false;
        }

//        List<UserCrossRechargeActTask> userRechargeActTaskList = getUserCrossRechargeActTaskList(userId, configId);
//        Map<Integer, UserCrossRechargeActTask> userRechargeActTaskMap = new HashMap<>();
        JsonArray rechargeGetArray = userRankAct.getRechargeTaskGetArray();
//        for (UserCrossRechargeActTask userRechargeActTask : userRechargeActTaskList) {
//            if (userRechargeActTask.getRound() == round) {
//                userRechargeActTaskMap.put(userRechargeActTask.getTaskType(), userRechargeActTask);
//            }
//        }
        int[] rechargeTaskArray = actConfig.getRechargeTaskArray();
        List<Integer> rdArray = new ArrayList<>();
        for (int taskGroup : rechargeTaskArray) {
            List<ActRechargeTask> rechargeTaskList = new ArrayList<>(getActRechargeTaskList(taskGroup).values());
//            System.out.println("rechargeTaskList: ");
//            rechargeTaskList.stream().map(JsonObject::mapFrom).map(JsonObject::toString).forEach(System.out::println);
            for (ActRechargeTask rechargeTask : rechargeTaskList) {
//                UserCrossRechargeActTask userCrossRechargeActTask = userRechargeActTaskMap.get(rechargeTask.getTaskType());
                if (userRechargeActTask.getTaskType() != rechargeTask.getTaskType()) {
                    break;
                }
                if (Tool.isInList(rechargeGetArray, rechargeTask.getId())) {
                    continue;
                }
                if (oldP < rechargeTask.getNum() && userRechargeActTask.getCurP() >= rechargeTask.getNum()) {
                    if (!Tool.isInList(rdArray, rechargeTask.getTaskType())) {
                        rdArray.add(rechargeTask.getTaskType());
                    }
                    isRedPoint = true;
                    break;
                }
            }
        }
        if (isRedPoint) {
            GameUser.sendRedPointPrompt(userInfo, null, SystemConstant.RED_POINT_RANKACT_RED_POINT, SystemConstant.RED_POINT_RANKACT_SUB_TYPE_RECHARGE, configId, rdArray);
        }
        return isRedPoint;
    }

    public static boolean checkCrossRankRedPoint(UserInfo userInfo, CsGameSystem.CSGameSystemRedPointResponse.Builder builder) {
        long curTime = TimeUtils.getCurTime();
        JsonObject actInfo = isCrossRankAct(curTime);
        if (actInfo == null) {
            return false;
        }
        ServerInfo serverInfo = ServerManager.getServerInfo(userInfo.getServerId());
        long round = actInfo.getLong("round");
        int configId = actInfo.getInteger("actid");
        if (!isJoinCrossRankAct(serverInfo, round)) {
            return false;
        }

        ActConfig actConfig = RankActManager.getActConfig(configId);
        if (actConfig == null) {
            return false;
        }
        long userId = userInfo.getId();
        UserCrossRankAct userRankAct = RankActManager.getUserCrossRankAct(userId, configId);
        if (userRankAct == null || userRankAct.getRound() != round) {
            return false;
        }
        boolean isRedPoint = false;
        List<UserCrossRankActTask> userCrossRankActTaskList = RankActManager.getUserCrossRankActTaskList(userId, configId);
        Map<Integer, UserCrossRankActTask> userCrossRankActTaskMap = new HashMap<>();
        for (UserCrossRankActTask task : userCrossRankActTaskList) {
            if (task.getRound() == round) {
                userCrossRankActTaskMap.put(task.getTaskType(), task);
            }
        }
        CsGameSystem.RedPoint_RankactReward.Builder redPoint = CsGameSystem.RedPoint_RankactReward.newBuilder();
        int[] taskTypeArray = actConfig.getTimeTaskArray();
        JsonArray taskGetArray = userRankAct.getTaskGetArray();
        for (int taskGroup : taskTypeArray) {
            List<ActTask> taskList = ActDaysManager.getActTasksByGroupId(taskGroup);
            for (ActTask task : taskList) {
                UserCrossRankActTask userTask = userCrossRankActTaskMap.get(task.getTaskType());
                if (userTask == null) {
                    continue;
                }
                if (Tool.isInList(taskGetArray, task.getTaskType())) {
                    continue;
                }
                if (userTask.getCurP() >= task.getNum1()) {
                    redPoint.setConfigId(configId);
                    redPoint.addTaskGroups(taskGroup);
                    isRedPoint = true;
                    break;
                }
            }
        }
        List<UserCrossRechargeActTask> userRechargeActTaskList = getUserCrossRechargeActTaskList(userId, configId);
        Map<Integer, UserCrossRechargeActTask> userRechargeActTaskMap = new HashMap<>();
        JsonArray rechargeGetArray = userRankAct.getRechargeTaskGetArray();
        for (UserCrossRechargeActTask userRechargeActTask : userRechargeActTaskList) {
            if (userRechargeActTask.getRound() == round) {
                userRechargeActTaskMap.put(userRechargeActTask.getTaskType(), userRechargeActTask);
            }
        }
        int[] rechargeTaskArray = actConfig.getRechargeTaskArray();
        for (int taskGroup : rechargeTaskArray) {
            List<ActRechargeTask> rechargeTaskList = new ArrayList<>(getActRechargeTaskList(taskGroup).values());
            for (ActRechargeTask rechargeTask : rechargeTaskList) {
                UserCrossRechargeActTask userCrossRechargeActTask = userRechargeActTaskMap.get(rechargeTask.getTaskType());
                if (userCrossRechargeActTask == null) {
                    continue;
                }
                if (Tool.isInList(rechargeGetArray, rechargeTask.getId())) {
                    continue;
                }
                if (userCrossRechargeActTask.getCurP() >= rechargeTask.getNum()) {
                    redPoint.setConfigId(configId);
                    redPoint.addRechargeTasks(rechargeTask.getTaskType());
                    isRedPoint = true;
                    break;
                }
            }
        }
        long etime = actInfo.getLong("etime");
        long closetime = actInfo.getLong("closetime");
//        long stime = actInfo.getLong("stime");
        if (curTime < etime + 5 * TimeUtils.MINUTE || curTime > closetime) {
            if (isRedPoint) {
                builder.setRankactReward(redPoint);
            }
            return isRedPoint;
        }

        List<ActTopRanking> actTopRankings = getActTopRankingList(actConfig.getRankList());
        if (actTopRankings == null || actTopRankings.isEmpty()) {
            if (isRedPoint) {
                builder.setRankactReward(redPoint);
            }
            return isRedPoint;
        }
        JsonArray rankGet = userRankAct.getRankGetArray();
        for (ActTopRanking actTopRanking : actTopRankings) {
            int rankType = actTopRanking.getType();
            long rankId = RankActManager.getRankId(actConfig.getConfigId(), (byte) rankType);
            if (Tool.isInList(rankGet, rankType)) {
                continue;
            }
            String rankKey = RankActManager.getCrossUserRankKey(rankId, serverInfo.getWarZone(), round);
            Long myRank = null;
            UserUnion userUnion = UnionManager.getUserUnion(userId);
            if (rankType == ActTopRanking.RANK_TYPE_UNION_EXP) {
                if (userUnion.getUnionId() > 0) {
                    myRank = Future.await(RedisTools.getMyRank(rankKey, userUnion.getUnionId() + ""));
                }
            } else {
                myRank = Future.await(RedisTools.getMyRank(rankKey, String.valueOf(userId)));
            }
            if (myRank != null && myRank <= actTopRanking.getList()) {
                redPoint.setConfigId(configId);
                redPoint.setIsReward(true);
                isRedPoint = true;
                break;
            }
        }
        int[] shopIdArray = actConfig.getShopIdArray();
        for (int shopId : shopIdArray) {
            Shop shop = ShopManager.getShop(shopId);
            if (shop == null) {
                continue;
            }
            if (shop.getIsFree() == 1) {
                UserCrossRankActShop userCrossRankActShop = getUserCrossRankActShop(userId, configId, shopId);
                int buyNum;
                if (userCrossRankActShop != null) {
                    userCrossRankActShop.checkRound(round);
                    buyNum = userCrossRankActShop.getNum();
                } else {
                    buyNum = 0;
                }
                if (shop.getLimitNum() == 0 || buyNum < shop.getLimitNum()) {
                    redPoint.setIsFreeShop(true);
                    isRedPoint = true;
                }
            }
        }
        if (isRedPoint) {
            builder.setRankactReward(redPoint);
        }
        return isRedPoint;
    }

}
